开发者问题收集

修复“致命的 Python 错误:Py_Initialize:无法初始化 sys 标准流”

2021-03-23
6218

我有 两个不同版本的python环境 ,它们 并行运行 。当我在一个python环境中执行另一个python环境中的python脚本( test2.py )时,出现以下错误:

Fatal Python error: Py_Initialize: can't initialize sys standard streams
Traceback (most recent call last):
  File "C:\ProgramData\Miniconda3\envs\GMS_VENV_PYTHON\lib\io.py", line 52, in <module>
  File "C:\ProgramData\Miniconda3\envs\GMS_VENV_PYTHON\lib\abc.py", line 147
    print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
                                                      ^
SyntaxError: invalid syntax

所以我的设置是这样的:

Python 3.7
 (test.py)
    │
    │                           Python 3.5.6
    ├───────────────────────────────┐
    ┆                               │
    ┆                         execute test2.py
    ┆                               │
    ┆                           🗲 Error

我该如何解决这个问题?

对于 -people :如何在Digital Micrograph中执行具有不同python版本的模块?


详细信息

我有两个python文件。

文件1 ( test.py ):

# execute in Digital Micrograph
import os
import subprocess

command = ['C:\\ProgramData\\Miniconda3\\envs\\legacy\\python.exe', 
           os.path.join(os.getcwd(), 'test2.py')]
print(*command)

result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("Subprocess result: '{}', '{}'".format(result.stdout.decode("utf-8"), result.stderr.decode("utf-8")))

和文件 2( test2.py

# only executable in python 3.5.6
print("Hi")

在同一目录中。 test.py 正在使用不同的 Python 版本(Python 3.5.6, legacy 环境)执行 test2.py

我的 Python 脚本( test.py )正在第三方程序( Digital Micrograph )的 Python 解释器中运行。此程序会安装一个名为 GMS_VENV_PYTHON (python 版本 3.7.x)的 miniconda python 环境,可在上述回溯中看到。 legacy miniconda 环境仅用于在 python 版本 3.5.6 中运行 test2.py (来自 test.py )。

当我从命令行运行 test.py 时(也在 conda GMS_VENV_PYTHON 环境中),我从 test.py 中的 test2.py 获得了预期的输出。当我在 Digital Micrograph 中运行完全相同的文件时,我得到了响应

Subprocess result: '', 'Fatal Python error: Py_Initialize: can't initialize sys standard streams
Traceback (most recent call last):
  File "C:\ProgramData\Miniconda3\envs\GMS_VENV_PYTHON\lib\io.py", line 52, in <module>
  File "C:\ProgramData\Miniconda3\envs\GMS_VENV_PYTHON\lib\abc.py", line 147
    print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
                                                      ^
SyntaxError: invalid syntax
'

这告诉我以下内容(我猜):

  • 调用 test2.py ,因为这是子进程调用的错误输出。因此 subprocess.run() 函数似乎运行正常
  • 路径位于 GMS_VENV_PYTHON 环境中,而 在这种情况下是错误的 。由于这是 test2.py ,它们应该位于 legacy 路径中
  • 出现 SyntaxError ,因为使用了 f-string(文字字符串插值) ,该字符串是在 Python 3.6 中引入的。因此执行的 Python 版本在 3.6 之前。因此,使用的是 legacy python 环境。
  • test2.py 既使用 io ,也不使用 abc (我不知道该得出什么结论;执行 python 时这些模块是否默认加载?)

所以我猜这意味着,标准模块是从错误的目的地加载的(我不知道为什么,可能是因为它们总是被加载)。

我该如何解决这个问题? (有关更多详细信息,请参阅 我尝试过的方法 > PATH


我迄今为止尝试过的方法

编码

我看到了这篇文章“ 致命 Python 错误:Py_Initialize:无法初始化系统标准流 LookupError:未知编码:65001 ”,它告诉我编码可能存在问题。我知道 Digital Micrograph 内部使用 ISO 8859-1。我尝试使用 python -X utf8python -X utf8test2.py 不关心 UTF-8,它仅是 ASCII),如下所示。但它们都不起作用

command = ['C:\\ProgramData\\Miniconda3\\envs\\legacy\\python.exe', 
           "-X", "utf8=0", 
           os.path.join(os.getcwd(), 'test2.py')]

PATH

据我所知,我认为这就是问题所在。帖子“ PyCharm:Py_Initialize:无法初始化 sys 标准流 ”的答案“ https://stackoverflow.com/a/31877629/5934316 ”建议更改 PYTHONPATH

因此,要具体说明我的问题:

  1. 这是可行的方法吗?
  2. 如何仅为子进程设置 PYTHONPATH (同时在主线程中执行带有其他库的 python)?
  3. 有没有更好的方法可以同时拥有两个不同的 python 版本时间?

感谢您的帮助。


背景

我目前正在编写一个处理电子显微镜的程序。我需要 Digital Micrograph 的“环境”(图形界面、帮助工具以及硬件访问)。所以没有办法使用它。而且 DigitalMicrograph 只支持 python 3.7。

另一方面,我需要一个仅适用于 python 3.5.6 的外部模块。而且没有办法绕过使用这个模块,因为它控制其他硬件。

两者都依赖于 python C 模块。由于它们已经编译,因此无法检查它们是否与其他版本兼容。此外,它们控制高度敏感的光圈,而人们不想更改代码。简而言之:我需要两个并行的 python 版本。

2个回答

实际上我差点就猜到了。问题是 python 从错误的位置导入了无效模块 。在我的例子中,由于路径错误,模块是从另一个 python 安装中导入的。根据“ https://stackoverflow.com/a/4453495/5934316 ”修改 PYTHONPATH 适用于我的示例。

import os

my_env = os.environ.copy()
my_env["PYTHONHOME"] = "C:\\ProgramData\\Miniconda3\\envs\\legacy"
my_env["PYTHONPATH"] = "C:\\ProgramData\\Miniconda3\\envs\\legacy;"
my_env["PATH"] = my_env["PATH"].replace("C:\\ProgramData\\Miniconda3\\envs\\GMS_VENV_PYTHON", 
                                        "C:\\ProgramData\\Miniconda3\\envs\\legacy")

command = ["C:\\ProgramData\\Miniconda3\\envs\\legacy\\python.exe", 
           os.path.join(path, "test2.py")]

result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=my_env)

对于 Digital Micrograph 用户:python 环境保存在“Private:Python:Python Path”中的全局​​标记中。因此替换:

import DigitalMicrograph as DM

# ...

success, gms_venv = DM.GetPersistentTagGroup().GetTagAsString("Private:Python:Python Path")

if not success:
    raise KeyError("Python path is not set.")

my_env["PATH"] = my_env["PATH"].replace(gms_venv, "C:\\ProgramData\\Miniconda3\\envs\\legacy")
miile7
2021-03-23

我之前曾将我的 python(基本)环境中的“PYTHONPATH”设置为“D:\ProgramData\Anaconda3”,但我发现当我切换到另一个环境时,我的 python 仍然从“D:\ProgramData\Anaconda3”导入基本 python 包,这意味着它通过错误的“系统环境变量”配置获取了错误的基本包。

因此,我从 Windows“系统环境变量”中删除了“PYTHONPATH”,这样就解决了。

tridu33
2021-12-01