我试图整理一个使用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_register
和PyCodec_Register
都应该如此。只是在代码中没有任何一个被调用的函数。
我真的不知道这意味着什么,因为我仍然不知道应该何时以及从何处调用这些函数。从我的其他python构建(3.1.3)的源代码中完全没有引发错误的代码。
编辑2
我在下面回答了我自己的问题。
检查PYTHONPATH
和PYTHONHOME
环境变量,确保它们不指向Python 2.x.
我遇到了问题,正在修补这里提到的不同解决方案。因为我从Visual Studio运行我的项目,显然,我需要在Visual Studio中设置环境路径而不是系统路径。
在项目解决方案\ properties \ environment中添加一个简单的PYTHONHOME = PATH \ TO \ PYTHON \ DIR解决了这个问题。
对我来说,当我将Python 64位从3.6.4更新到3.6.5时就发生了这种情况。它抛出了一些错误,比如“无法解压缩python.dll。你有权限。”
Pycharm也无法加载解释器,即使我在设置中重新加载它。运行python
命令会出现相同的错误,无论是否有管理员模式。
安装Python时出错,包含python安装目录C:\ Users \ USERNAME \ AppData \ Local \ Programs \ Python \ Python36中的文件夹丢失
重新安装Python也可以解决问题。(不删除和安装)
再次卸载Python和安装Python。
因为运行安装程序只是提取除include文件夹之外的相同文件
我有同样的问题,发现了这个问题。但是从这里的答案我无法解决我的问题。我开始调试cpython代码,并认为我可能会发现一个bug。因此我在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的内容我发现了两件事。
C:\Work\build\product\python37.zip
有正确的路径'C:\Work\build\product\'
。没有zip文件。我的所有文件和目录都已解压缩。所以我将文件压缩到名为python37.zip的存档,这解决了导入错误。我尝试的下一件事是在调用C:\Users\rvq\AppData\Roaming\Python\Python37\site-packages
之前使用C:\Work\build\product\Lib\site-packages
。这导致了
致命Python错误'无法加载文件系统编码'ModuleNotFoundError:没有名为'encodings'的模块
我用这两个调用创建了一个最小的c ++项目,并开始调试Cpython。
Py_SetPath(L"C:/Work/build/product/Lib/site-packages")
我跟踪了Py_Initialize()
的电话
int main()
{
Py_SetPath(L"C:/Work/build/product/Lib/site-packages");
Py_Initialize();
}
在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的路径。这是预期的行为还是一个错误?如果它不是一个bug有没有办法改变它,以便它也可以检测目录?
PS:使用Python 3.5.2+时,我没有发生ModuleNotFoundError,这是我之前在项目中使用的版本。我还检查了我是否设置了任何PYTHONHOME或PYTHONPATH环境变量,但我没有在我的系统上看到其中一个。
回答
这可能是文档失败的最重要因素。我们正在重新设计初始化,所以这是提供这种反馈的好时机。
简短的回答是,您需要确保Python可以找到Py_Initialize()
目录,通常是将标准库放在static int
zipimport_zipimporter___init___impl(ZipImporter *self, PyObject *path)
中。 Lib/encodings
清除所有推断路径,因此您需要指定Python应该看到的所有位置。 (Python自动查看的规则很复杂,因平台而异,这是我很想解决的问题。)
不存在的路径是可以的,那就是zip文件。您可以选择将stdlib放入zip中,如果将其命名为默认路径,则会自动找到它,但您也可以将其解压缩并引用该目录。
完全嵌入式嵌入比我准备在手机上打字更多。希望这足以让你现在开始。
在我的情况下,对于Windows,如果您安装了多个python版本,如果sys.path
指向一个版本,则其他版本不起作用。我发现,如果你只是删除Py_SetPath
,他们都工作正常
之前已经提到了部分内容,但简而言之,这对我的环境有用,我有多个Python安装和我的全局操作系统环境设置指向不同的安装,而不是我遇到的时候尝试使用的安装。问题。
确保您的(本地或全球)环境完全设置为指向您要使用的安装,例如你有两个(或更多)安装,比方说python27和python33(对不起这些是windows路径,但以下内容对于等效的UNIX风格路径也应该有效,请让我知道我在这里缺少的任何东西(可能DLLs路径可能不同)):
C:\python27_x86
C:\python33_x64
现在,如果您打算使用python33安装,但您的全局环境指向python27,请确保您更新环境(而PATH
和PYTHONHOME
可能是可选的(例如,如果您暂时在本地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
,但正确设置DLLs
,Lib
和site-packages
是最重要的。
希望这可以帮助。
核心原因很简单:Python没有找到它的模块目录,所以当然也不能加载encodings
Python doc on embedding说“Py_Initialize()
根据其最佳猜测计算模块搜索路径”......“特别是,它查找名为lib/pythonX.Y
的目录”
然而,如果模块安装在(仅)lib
- 相对于python二进制文件 - 上面的猜测是错误的。
虽然文档说PYTHONHOME
和PYTHONPATH
被认为是,但我们观察到情况并非如此;他们的实际存在或内容完全无关紧要。
唯一产生影响的是调用Py_SetPath()
,例如[path-to]\lib
作为Py_Initialize()
之前的论据。
当然,这只是嵌入场景的一个选项,其中一个人可以直接访问和控制代码;使用现成的解决方案,可能需要特殊步骤来解决问题。
尝试在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
(取代适当的版本号),它会正常工作。
从python3k开始,启动需要编码模块,可以在PYTHONHOME \ Lib目录中找到。实际上,API Py_Initialize()执行init并导入编码模块。确保PYTHONHOME \ Lib在sys.path中并检查编码模块是否在那里。
我刚刚遇到了完全相同的问题(相同的Python版本,操作系统,代码等)。
您只需要在程序的工作目录中复制Python的Lib /目录(在VC上它是.vcproj所在的目录)
发布版本似乎出现了问题,或者未能包含相应的编解码器,或者错误地识别用于系统API的编解码器。由于python_d
可执行文件正在运行,os.getfsencoding()
的回报是什么? (使用C API在Initialize / Finalize调用之间调用)
我有这个问题与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导入文件的其他奇怪错误。
因此,由于某种原因,python dll无法找到编码模块。 python.exe可执行文件显然找到它,因为它具有预期的相对路径。修改搜索路径有效。
所有这一切的原因?不知道,但至少它是有效的。我非常怀疑某个地方有一个错字,这通常是看起来奇怪的错误的原因。