【问题标题】:Importing wrong packages when calling a python script from another python script via subprocess通过子进程从另一个 python 脚本调用 python 脚本时导入错误的包
【发布时间】:2014-09-18 12:54:19
【问题描述】:

我正在尝试使用 cx_Freeze 为我的 32 位和 64 位程序自动创建可执行文件。我有两个单独的 python 3.4 安装(32 位和 64 位),其中包含所有必需的包,它们都对应于它们相应的架构。

但是,当我执行通过子进程调用不同 python 安装的脚本时,被调用的 python 子进程导入了错误的包。他们导入包,原始脚本是从中调用的,不是在子进程中调用的 python 安装包。

使用 64 位 python 调用的最小示例:

#! coding=utf-8
import subprocess as sp
sp.call(["python34-32","test.py"])
sp.call(["python34","test.py"])

test.py 仅包含以下行:

import cx_Freeze

第二个进程,也调用 64 位 python 不会有问题。但是32bit会抛出如下错误:

ImportError: DLL load failed: %1 is not a valid Win32 application.

这是因为调用 32 位 python 的子进程从 64 位 python 导入 cx_freeze。情况也可以逆转。使用32位python执行主脚本时,出现同样的错误,但是现在是因为在suprocess中调用的64位python正在导入32位冻结包。

我怎样才能停止这种行为并告诉它从适当的来源导入?

我正在使用 Windows 7 x64 和 PyDev 作为 IDE,以防万一,它可能是相关的。

编辑:显然,当从源目录中的命令行执行主脚本时,它可以工作。感谢下面的 cmets,我猜这个问题与 PyDev 如何设置环境变量有关。

【问题讨论】:

  • 可能是环境问题?子进程继承了当前环境,因此,新的解释器可能正在查看错误的PYTHONPATH
  • 对了,你知道使用shell=Truesecurity considerations吗?如果您没有使用任何特定于 shell 的功能,您应该指定shell=True,只需执行:sp.call(['python34-32', 'test.py'])。如果你不喜欢将命令写成列表,你可以使用shlex.splitimport shlex; sp.call(shlex.split('python34-32 test.py'))
  • 如果您在同一目录中从命令行运行python34-32 test.py 会发生什么?
  • @Bakuriu: shlex.split() 使用 sh 语法,在 Windows 上不是很有用。
  • @j-f-sebastian 从命令行它在这两种情况下都有效,但我不知道为什么......很迷人!

标签: python import subprocess pydev cx-freeze


【解决方案1】:

显然,PyDev 设置了环境变量 PYTHONPATH,这是 两个 子进程用来加载其包的路径。

如果我在 64 位 python 中执行以下脚本:

#! coding=utf-8
import subprocess as sp

sp.call(["python34-32", "test.py"])

test.py 包含以下行:

import os
print(os.getenv("PYTHONPATH"))

结果显示为 64 位 python 安装设置的标准文件夹。

我的猜测是,我必须在调用 32 位 python 之前更改 PYTHONPATH 变量。有人知道怎么做吗?

编辑:在子进程的环境中更改 PYTHONPATH 变量就可以了。在 64 位 python 中执行以下操作将起作用

#! coding=utf-8
import subprocess as sp
import os

env = os.environ
env["PYTHONATH"] = "{INSERT FOLDERS TO 32bit PYTHON}"
sp.call(["python34-32", "test.py"], env=env)

感谢 bakuriu 让我走上正轨。

【讨论】:

  • 在 Python 脚本中,检查 sys.pathPYTHONPATH 只是其中的一部分。即使您在传递给子进程之前删除 PYTHONPATH envvar:del env["PYTHONPATH"}call(["python34-32", "test.py"]) 也应该可以工作。
猜你喜欢
  • 2015-08-31
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多