Py_Initialize失败-无法加载文件系统编解码器


70

我试图将使用嵌入式python 3.2解释器的简单c ++测试项目放在一起。项目构建良好,但是Py_Initialize引发了致命错误:

Fatal Python error: Py_Initialize: unable to load the file system codec
LookupError: no codec search functions registered: can't find encoding

最小代码:

#include <Python.h>

int main (int, char**)
{
  Py_Initialize ();
  Py_Finalize ();
  return 0;
}

操作系统是32位Vista。

使用的python版本是python 3.2调试版本,使用VC ++ 10从源代码构建。

来自同一构建的python_d.exe文件可以正常运行。

有人可以解释这个问题以及如何解决吗?我自己的google-fu使我失望。

编辑1

经过python源代码后,我发现,如错误所示,尚未注册任何编解码器搜索功能。两者codec_registerPyCodec_Register应有的状态。只是在代码中没有任何这些函数被调用。

我真的不知道这意味着什么,因为我仍然不知道应该在何时何地调用这些函数。我的其他python版本(3.1.3)的源代码中完全缺少引发错误的代码。

编辑2

在下面回答了我自己的问题。

Answers:


50

检查PYTHONPATHPYTHONHOME环境变量,并确保它们未指向Python2.x。

http://bugs.python.org/issue11288


1
PYTHONPATH和PYTHONHOME系统变量在哪里?是否应该在“属性” /“高级系统设置” /“环境变量” /“系统变量”中?如果是的话,我什么都没有,那么我就把自己的anaconda env放在了相应的路径上。但是那个时候conda终端没有运行。
bit_scientist

1
@voo_doo在shell上,您可以使用例如进行检查echo $PYTHONPATH。取消设置unset PYTHONPATH
分拆

38

这部分之前已经提到过,但简而言之,这是我的环境,让我有多个Python的安装和我的全球操作系统环境设置为指向什么工作不同的安装比我尝试工作遇到的时问题。

确保已完全设置(本地或全局)环境,以指向要使用的安装,例如,您有两个(或多个)安装,例如python27和python33(对不起,这些是Windows路径,但是以下内容也应等效于等效的UNIX风格的路径,请让我知道我在这里缺少的任何内容(DLL路径可能有所不同):

C:\python27_x86

C:\python33_x64

现在,如果您打算使用python33安装,但是您的全局环境指向python27,请确保您这样更新环境(whilePATHPYTHONHOME 可能是可选的(例如,如果您临时在本地shell中工作)):

PATH="C:\python33_x64;%PATH%"

PYTHONPATH="C:\python33_x64\DLLs;C:\python33_x64\Lib;C:\python33_x64\Lib\site-packages"

PYTHONHOME=C:\python33_x64

请注意,您可能需要/想任何其他库路径添加到您PYTHONPATH如果需要通过你的开发环境,但有你的DLLsLibsite-packages适当建立是最重要的。

希望这可以帮助。


1
我在pythonnet中遇到了这个问题。追加Lib文件夹的路径即可达到PythonEngine.PythonPath目的。谢谢!
sebrockm

谢谢。我遇到了没有编码模块的问题。设置以上的PYTHONPATH对我有用。
余辉于

很高兴听到这有帮助!
bossi

@bossi当我确实喜欢您提到的时候(但仅限于anaconda env),conda终端无法正常工作。
bit_scientist

@voo_doo-我不熟悉anaconda env,但作为环境管理器,它可能包装了这些env变量,并且可能需要自定义更新/配置 PATHPYTHONPATHPYTHONHOME等?
bossi

22

其核心原因很简单:Python没有找到它的modules目录,所以它当然可以不加载encodings,过

嵌入的Python文档说“Py_Initialize()根据其最佳猜测来计算模块搜索路径” ...“尤其是,它将查找名为lib/pythonX.Y”的目录

但是,如果lib相对于python二进制文件(只是)安装了模块,则上述猜测是错误的。

尽管文档说了这一点PYTHONHOMEPYTHONPATH得到了重视,但我们观察到情况并非如此。它们的实际存在或内容完全无关紧要。

是有效果的唯一的事情就是打电话Py_SetPath()与例如[path-to]\lib作为参数之前 Py_Initialize()

当然,这仅是嵌入式方案的一种选择,在这种方案中,人们可以直接访问和控制代码。对于现成的解决方案,可能需要采取特殊步骤来解决此问题。


2
最好和最准确的答案,IMO。投票了!
Leslie N

^莱斯利说了什么。
mlvljr

7

尝试在Mac OS下安装brew的python3遇到同样的事情!这里的问题是,在Mac OS中,自制软件使“真实”的python比您想象的要深一层。您会从自制程序输出中认为

$ echo $PYTHONHOME
/usr/local/Cellar/python3/3.6.2/
$ echo $PYTHONPATH
/usr/local/Cellar/python3/3.6.2/bin

是正确的,但是调用$ PYTHONPATH / python3会因中止6“找不到编码”而立即崩溃。这是因为尽管$ PYTHONHOME看起来像是一个完整的安装,带有bin,lib等,但它不是真正的Python,它位于Mac OS的“框架”中。做这个:

PYTHONHOME=/usr/local/Cellar/python3/3.x.y/Frameworks/Python.framework/Versions/3.x
PYTHONPATH=$PYTHONHOME/bin

(适当地替换版本号),它将正常工作。


谢谢!第二个示例可在我的macOS上完美运行:-)
CeDeROM

使用pyenv和zsh,还有助于取消设置变量,而不是将其设置为空。
peterhil

5

在python3k中,启动需要编码模块,该模块可以在PYTHONHOME \ Lib目录中找到。实际上,API Py_Initialize()进行了初始化并导入了编码模块。确保PYTHONHOME \ Lib在sys.path中,并检查其中的encodings模块。


5

我在python 3.5,anaconda 3,Windows 7 32位上遇到了这个问题。我通过将pythonX.lib和pythonX.dll文件移动到我的工作目录并调用来解决此问题

Py_SetPythonHome(L"C:\\Path\\To\\My\\Python\\Installation");

在初始化之前,它可以找到所需的标头,我的路径是“ ... \ Anaconda3 \”。我需要调用Py_SetPythonHome的额外步骤,否则我将在python导入文件的地方遇到其他奇怪的错误。


还提供给pybind11
heLomaN

4

我只是遇到了完全相同的问题(相同的Python版本,操作系统,代码等)。

您只需要在程序的工作目录中复制Python的Lib /目录(在VC上是.vcproj所在的目录)


5
那可能行得通,但我会说这不是一个很好的解决方案。它不能解决为什么搜索路径错误的问题,只能避免它,并且还会弄乱目录树。我建议在(IIRC)中的find_module函数Python/import.c和/或calculate_path函数中设置一个断点,PC/getpathp.c以找出它的实际位置以及为什么它不是您期望的。就是说,在这些方面,我可能是一位完美主义者。
安东

1
我不同意 这是一个非常有效的解决方案:您嵌入自己的Python,知道它的位置和包含的内容。它也更容易重新分发(记得在Blender的旧时代,当您必须安装正确版本的Python或它在运行时崩溃时吗?现在它捆绑在ProgramFiles / Blender /中。)我猜这取决于您的用法。
Calvin1602 2012年

哦,等等...你的意思是(写了我现在看到的)复制目录不是吗?我在复制目录内容时读到它,这很混乱……很抱歉。
安东

我在python 3.5,Anaconda 4.0发行版中遇到了这个问题。这已经解决了,谢谢
aquirdturtle '16

3

发布版本似乎出了点问题,要么没有包含适当的编解码器,要么错误地标识了用于系统API的编解码器。由于python_d可执行文件正在运行,因此返回的是os.getfsencoding()什么?(使用C API在Initialize / Finalize调用之间进行调用)


调试告诉我sys.getfilesystemencoding正确返回了“ mbcs”。
安东

如果创建3.2的发布版本并从发布模式可执行文件中链接该链接,会发生什么情况?
ncoghlan 2011年

3

我有同样的问题,发现了这个问题。但是从这里的答案我无法解决我的问题。我开始调试cpython代码,并认为可能会发现我的错误。因此,我在python问题跟踪器上打开了一个问题。

我的错误是我不明白这会Py_SetPath清除所有推断的路径。因此,在调用此函数时,需要设置所有路径。

为了完整起见,我还复制了下面对话的最重要部分。


我的原始问题文字

我自己在Windows上使用Visual Studio 2017编译了CPython 3.7.3的源代码以及一些软件包,例如numpy。当我启动Python解释器时,我能够导入并使用numpy。但是,当我通过C-API运行相同的脚本时,ModuleNotFoundError

因此,我要做的第一件事是检查numpy是否在我的site-packages目录中,并且确实存在一个名为numpy-1.16.2-py3.7-win-amd64.egg的文件夹。(之所以有意义是因为python解释器可以找到numpy)

我要做的下一件事是获取有关通过C-API运行脚本时创建的sys.path变量的一些信息。

#### sys.path content ####
C:\Work\build\product\python37.zip
C:\Work\build\product\DLLs
C:\Work\build\product\lib
C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2017\PROFESSIONAL\COMMON7\IDE\EXTENSIONS\TESTPLATFORM
C:\Users\rvq\AppData\Roaming\Python\Python37\site-packages

检查sys.path的内容时,我注意到两件事。

  1. C:\Work\build\product\python37.zip有正确的路径' C:\Work\build\product\'。没有压缩文件。我所有的文件和目录都已解压缩。因此,我将文件压缩到名为python37.zip的存档中,这解决了导入错误。

  2. C:\Users\rvq\AppData\Roaming\Python\Python37\site-packages应该是错的,C:\Work\build\product\Lib\site-packages但我不知道如何创建错误的路径。

我尝试的下一件事情是Py_SetPath(L"C:/Work/build/product/Lib/site-packages")在致电之前使用Py_Initialize()。这导致

致命的Python错误“无法加载文件系统编码” ModuleNotFoundError:没有名为“ encodings”的模块

我使用这两个调用创建了一个最小的c ++项目,并开始调试Cpython。

int main()
{
  Py_SetPath(L"C:/Work/build/product/Lib/site-packages");
  Py_Initialize();
}

我追踪Py_Initialize()到的呼叫

static int
zipimport_zipimporter___init___impl(ZipImporter *self, PyObject *path)

在zipimport.c内部

此函数上方的注释指出:

创建一个新的zipimporter实例。“ archivepath”必须是zipfile或zipfile中特定路径的类似路径的对象。例如,如果mydirectory是归档文件中的有效目录,则可以是“ /tmp/myimport.zip”或“ /tmp/myimport.zip/mydirectory”。如果“ archivepath”未指向有效的Zip存档,则引发“ ZipImportError”。zipimporter对象的'archive'属性包含目标zipfile的名称。

因此,对于我来说,似乎C-API期望使用Py_SetPath设置的路径是zipfile的路径。这是预期的行为还是错误?如果不是错误,是否有办法更改它,以便它也可以检测目录?

PS:使用Python 3.5.2+(这是我之前在项目中使用的版本)时,我没有发生ModuleNotFoundError。我还检查了是否设置了任何PYTHONHOME或PYTHONPATH环境变量,但在系统上没有看到其中之一。


回答

这可能是文档失败最多的原因。不过,我们正处于重新设计初始化的过程中,因此是提供此反馈的好时机。

简短的答案是,您需要确保Python可以找到Lib/encodings目录,通常是通过将标准库放在中sys.pathPy_SetPath清除所有推断的路径,因此您需要指定Python应该看的所有位置。(Python自动显示位置的规则很复杂,并且因平台而异,我很想解决这个问题。)

路径不存在,这就是zip文件。您可以选择将stdlib放入zip文件中,如果将其命名为默认路径,则会自动找到该文件,但也可以将其解压缩并引用目录。

完整的嵌入过程远远超过了我准备在手机上键入的内容。希望这足以让您现在就出发。


2

我遇到了问题,正在修改此处提到的其他解决方案。显然,由于我是从Visual Studio运行项目的,因此我需要在Visual Studio中设置环境路径,而不是系统路径。

在项目解决方案\属性\环境中添加一个简单的PYTHONHOME = PATH \ TO \ PYTHON \ DIR解决了该问题。


2

对我来说,这是在我将Python 64位3.6.4更新到3.6.5时发生的。它引发了一些错误,例如“无法提取python.dll。您具有权限”。

即使我在设置中重新加载了Pycharm,也未能加载解释器。python使用和不使用管理员模式时,运行命令都给出相同的错误。

原因

安装Python时发生错误,Python安装目录C:\ Users \ USERNAME \ AppData \ Local \ Programs \ Python \ Python36中的include文件夹缺少中的

重新安装Python也可以解决该问题。(不删除并安装)

卸载Python,然后再次安装Python。

因为正在运行的安装程序只是提取包括include文件夹在内的相同文件


2

就我而言,对于Windows,如果您安装了多个python版本,则如果PYTHONPATH指向一个版本,则其他版本则无法正常工作。我发现,如果您只是删除PYTHONPATH它们,它们都可以正常工作


0

因此,由于某种原因,python dll无法找到编码模块。python.exe可执行文件显然可以找到它,因为它具有预期的相对路径。修改搜索路径有效。

所有这些的原因?不知道,但至少能奏效。我高度怀疑我的某个地方有错字,这通常是看起来奇怪的错误的原因。


3
您在这里谈论什么搜索路径?
Piotr Dobrogost,2011年

python查找模块的路径。这是前一段时间,所以我不记得确切的位置或方式。
安东

3
您能否显示您在解决方案中所做的修改?
Hack-R

@ Hack-R可悲的是,没有。我环顾四周,但找不到项目了,因为已经有几年了,所以很可能不再存在。我很遗憾没有机会给出更详细的答案。
安东

29
为什么这是一个可接受的答案?这个答案没有解决方案。
Ska

0

对于那些在工作Visual Studio只需添加includeLiblibs目录到Include DirectoriesLibrary DirectoriesProjects Properties -> Configuration Properties > VC++ Directories

例如,我Anaconda3在系统上使用并且正在使用Visual Studio 2015这是设置的样子(请注意Include和Library目录): 在此处输入图片说明

编辑:

还指出 PYTHONPATH您在用户Environment Variables部分中bossi设置。样本输入可以像这样(就我而言):

C:\Users\Master\Anaconda3\Lib;C:\Users\Master\Anaconda3\libs;C:\Users\Master\Anaconda3\Lib\site-packages;C:\Users\Master\Anaconda3\DLLs

似乎很有必要。

此外,您需要在用户环境变量中Visual Studio设置,然后重新启动PYTHONPATH才能使更改生效。

另请注意:

确保将PYTHONHOME环境变量设置为要使用的Python解释器。Visual Studio中的C ++项目依靠此变量来定位文件(例如python.h创建Python扩展时使用的文件)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.