PyDev 在从 Eclipse 内部运行 Python 脚本时弄乱编码设置



我尝试使用以下命令运行subprocess.Popen()

ros_version_retrieve = subprocess.Popen(["rosversion", "-d"], shell=False, stdout=subprocess.PIPE)
ros_version_retrieve.wait()

rosversion是 ROS 的一部分,允许通过调用rosversion <package>来检索给定软件包的版本,或者通过调用rosversion -d来检索已安装 ROS 的版本。在第一种情况下,我会得到一个像1.12.3这样的字符串,在第二种情况下我会得到kinetic(因为这是我目前正在使用的版本(。

我从终端启动 Eclipse,以便 IDE 中也可以使用PATH和其他几个变量:

PYTHONPATHis/usr/local/lib/python2.7/dist-packages:/home/user/catkin_ws/devel/lib/python2.7/dist-packages:/opt/ros/kinetic/lib/python2.7/dist-packages:/usr/local/lib/python3.5/dist-packages/:/opt/OpenCV/python/3.4:/opt/
  • OpenCV/python/2.7:/opt/ros/indigo/lib/python2.7/dist-packages
  • PATH/opt/Qts/5.9/bin:/opt/QtCreator-custom/bin:/usr/local/bin:/opt/MATLAB/R2012a/bin/:/home/user/bin:/home/user/catkin_ws/scripts:/opt/ros/kinetic/bin:/home/user/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/usr/games:/usr/local/games:/opt/Qts/5.9/bin:/snap/bin:/usr/lib/jvm/java-9-oracle/bin:/usr/lib/jvm/java-9-oracle/db/bin

我知道它很不整洁(我刚刚了解了virtualenv(,但到目前为止它已经工作了,没有任何问题。

当我从 PyDev(Eclipse Neon(内部运行第一行相同的代码时,我得到

致命的 Python 错误:Py_Initialize:无法获取区域设置编码
文件"/usr/lib/python2.7/encodings/init.py",第 123 行 引发编解码器注册表错误,\

^ 语法错误:语法无效

我还尝试使用特定的软件包调用rosversion,即

subprocess.Popen(["rosversion", "roscpp"], shell=False, stdout=subprocess.PIPE)

但我得到了同样的错误。这两个命令调用在我的终端中以及当我在 PyDev 之外调用我的脚本时都没有一个问题。

我一直在关注这个问题,寻找答案。取消设置我的PYTHONPATH然后在我的代码中手动设置它不是一种选择。我也非常确定可以找到该命令,因为我的代码中有多个其他位置,我调用rospack,基本上它提供的每个参数的组合,并且工作正常。从错误以及我的 PyDev 项目的设置中,我还确定调用了正确的解释器,即 Python 2.7 的解释器,而不是我系统上也有的 3.4 解释器。

由于这似乎(至少就我而言(是 PyDev 问题而不是系统范围的问题,我正在寻找一种解决方案,我不必更改脚本即可在 PyDev 中运行它。如果需要设置项目设置,请告知。


更新:

感谢您在下面回答。但是,弹出PYTHONPATH会导致rosversion失败,但这次是由于无法在内部导入rospkg(这是通过PYTHONPATH加载的ROS环境的一部分(。我的代码中没有import rospkg,因为这违背了我正在做的事情的目的 - ROS的外部配置工具甚至可以设置它,如果我导入和使用模块是不可能的作为它的一部分。

我的PYTHONHOME实际上是空的。如果我只添加建议的编码部分,则会发生与以前相同的错误 -PyInitializeCodecRegistryError等。

再次 - 如果我从 bash 启动它,脚本可以正常工作。只有当我从 PyDev 运行它时,它才会失败。

我认为问题是您在配置中混合了Python 2和Python 3路径。

即:从您的PYTHONPATH您有:

/usr/local/lib/python2.7/dist-packages 
/home/user/catkin_ws/devel/lib/python2.7/dist-packages <-- py2
/opt/ros/kinetic/lib/python2.7/dist-packages
/usr/local/lib/python3.5/dist-packages/  <- py3
/opt/OpenCV/python/3.4:/opt/OpenCV/python/2.7 
/opt/ros/indigo/lib/python2.7/dist-packages <-- py2

我认为为了安全起见,您应该创建所需的环境并将其传递给子进程调用,正确填充键:

  • 蟒蛇路径
  • 蟒蛇之家
  • PYTHONIOENCODING
  • PYTHONUNBUFFERED

比如:

env = os.environ.copy()
env.pop('PYTHONPATH', None)
env.pop('PYTHONHOME', None)
env['PYTHONIOENCODING'] = 'ascii'
env['PYTHONUNBUFFERED'] = '1'
subprocess.Popen(["rosversion", "-d"], env=env)

也许PATHLANG也可以添加到该列表中(不确定,这在很大程度上取决于您要启动的内容以及您使用的程序将读取哪些变量(。

我刚刚尝试了一些东西,它起作用了 - 我Popen()的命令列表如下所示:["python2.7", "/usr/local/bin/rosversion", "-d"],它有效!

由于访问GitHub的问题,我实际上无法访问rosversion的源代码,尽管我足够盲目,无法通过查看rospkg导入失败的错误来自己得出结论。

rospackrosversion不同,它是Python脚本。虽然在 bash shell 中调用它不会导致问题,但似乎在子进程中运行它需要我实际调用该子进程内的 Python 解释器并传递绝对路径(我可以使用which rosversion获得(。

最新更新