【问题标题】:Py_Initialize fails - unable to load the file system codecPy_Initialize 失败 - 无法加载文件系统编解码器
【发布时间】:2011-08-07 08:56:48
【问题描述】:

我正在尝试组合一个使用嵌入式 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

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

【问题讨论】:

    标签: c++ python


    【解决方案1】:

    检查 PYTHONPATHPYTHONHOME 环境变量并确保它们不指向 Python 2.x。

    http://bugs.python.org/issue11288

    【讨论】:

    • PYTHONPATH 和 PYTHONHOME 系统变量在哪里?它们应该在属性/高级系统设置/环境变量/系统变量中吗?如果是,我没有它们,然后我让自己放置我的 anaconda env 的相应路径。但是那个时候 conda 终端没有运行。
    • @voo_doo 在您的外壳上,您可以检查例如echo $PYTHONPATH。使用unset PYTHONPATH 取消设置。
    【解决方案2】:

    发布版本似乎出现问题,要么未能包含适当的编解码器,要么错误地识别了用于系统 API 的编解码器。由于python_d 可执行文件正在运行,那么os.getfsencoding() 会返回什么? (使用 C API 在 Initialize/Finalize 调用之间调用它)

    【讨论】:

    • 调试告诉我sys.getfilesystemencoding 正确返回'mbcs'。
    • 如果您创建 3.2 的发布版本并从您的发布模式可执行文件链接它会发生什么?
    【解决方案3】:

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

    这一切的原因是什么?不知道,但至少它有效。我高度怀疑我的某个地方有错字,这通常是出现奇怪错误的原因。

    【讨论】:

    • 你在说什么搜索路径?
    • python 查找模块的路径。这是不久前的事了,所以我不记得确切的地点或方式。
    • 您能否展示您在解决方案中做了哪些修改?
    • @Hack-R 遗憾的是没有。我环顾四周,但我再也找不到这个项目了,而且很可能已经不存在了,因为它已经有几年了。当我有机会时,我很遗憾没有给出更详细的答案。
    • 为什么这是一个公认的答案?这个答案没有解决方案。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 这可能有效,但我会说这不是一个很好的解决方案。它并没有解决为什么搜索路径错误的问题,只是避免了它,并且还弄乱了目录树。我建议在Python/import.c 中的find_module 函数和/或PC/getpathp.c (IIRC) 中的calculate_path 函数中放置一个断点,以找出它实际在哪里以及为什么它不是您所期望的。也就是说,在这些事情上,我可能有点完美主义者。
      • 我不同意。这是一个完全有效的解决方案:您嵌入了自己的 Python,您知道它在哪里以及它包含什么。它也更容易再分发(记得在 Blender 的旧时代,当你必须安装正确版本的 Python 否则它会在运行时崩溃?现在它捆绑在 ProgramFiles/Blender/ 中。)我想这取决于你的使用情况。
      • 哦等等...你的意思是(并且写了我现在看到的)复制目录,不是吗?我把它读作复制目录的内容,这会很混乱......对此感到抱歉。
      • 我在 python 3.5、Anaconda 4.0 发行版中遇到了这个问题。这解决了它,谢谢
      【解决方案6】:

      之前已经提到了其中的一部分,但简而言之,这适用于我的环境,我安装了多个 Python,并且我的全局操作系统环境设置指向一个不同的安装遇到问题时我尝试与之合作的那个。

      确保您的(本地或全球)环境完全设置为指向您打算使用的安装,例如你有两个(或更多)安装,比如说一个 python27 和 python33 (对不起,这些是 Windows 路径,但以下应该对等效的 UNIX 样式路径有效,请让我知道我在这里缺少的任何东西(可能 DLL 路径可能不同)):

      C:\python27_x86

      C:\python33_x64

      现在,如果您打算使用您的 python33 安装,但您的全局环境指向 python27,请确保更新您的环境(而 PATHPYTHONHOME 可能是可选的(例如,如果您暂时在本地 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 是首要的重要性。

      希望这会有所帮助。

      【讨论】:

      • 我在使用 pythonnet 时遇到了这个问题。将我的Lib 文件夹路径附加到PythonEngine.PythonPath 就可以了。谢谢!
      • 谢谢。我在没有名为 encodings 的模块时遇到了这个问题。按上述设置 PYTHONPATH 对我有用。
      • 很高兴听到它有帮助!
      • @bossi 当我确实像你提到的那样(但仅限于 anaconda env)时,conda 终端不起作用。
      • @voo_doo - 我不熟悉 anaconda 环境,但作为环境管理器,它可能会包装这些环境变量,并且可能需要自定义更新/配置 PATHPYTHONPATHPYTHONHOME等等?
      【解决方案7】:

      我在使用 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
      【解决方案8】:

      在 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 会立即崩溃,并出现 abort 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 上完美运行 :-)
      • 使用 pyenv 和 zsh 它还有助于取消设置变量而不是将它们设置为空。
      【解决方案9】:

      在我的情况下,对于 Windows,如果您安装了多个 python 版本,如果 PYTHONPATH 指向一个版本,则其他版本不起作用。我发现如果你只删除PYTHONPATH,它们都可以正常工作

      【讨论】:

        【解决方案10】:

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

        在项目 solution\properties\environment 中添加一个简单的 PYTHONHOME=PATH\TO\PYTHON\DIR 即可解决问题。

        【讨论】:

          【解决方案11】:

          这发生在我将 Python 64 位3.6.4 更新到 3.6.5 时。它抛出了一些错误,例如 “无法提取 python.dll。你有权限吗。”

          Pycharm 也无法加载解释器,即使我在设置中重新加载了它。运行python 命令给出了同样的错误,无论是否有管理员模式。

          原因

          Python安装出错,python安装目录中include文件夹C:\Users\USERNAME\AppData\Local\Programs\Python\Python36丢失

          重新安装 Python 也能解决问题。(不是删除和安装)

          解决方案

          卸载 Python 并再次安装 Python。

          因为运行安装程序只是提取相同的文件,不包括包含文件夹

          【讨论】:

            【解决方案12】:

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

            Python doc on embedding 说“Py_Initialize() 根据其最佳猜测计算模块搜索路径”...“特别是,它会查找名为 lib/pythonX.Y 的目录”

            然而,如果模块安装在(只是)lib - 相对于 python 二进制文件 - 上面的猜测是错误的。

            虽然文档说PYTHONHOMEPYTHONPATH 被视为,但我们观察到情况并非如此;它们的实际存在或内容完全不相关。

            唯一有效的是调用Py_SetPath(),例如[path-to]\lib 作为参数之前 Py_Initialize()

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

            【讨论】:

            • 最佳和最准确的答案,IMO。已投票!
            • ^ 莱斯利所说的。
            【解决方案13】:

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

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

            为了完成,我还复制了下面对话中最重要的部分。


            我的原始问题文本

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

            所以我做的第一件事是检查 numpy 是否在我的站点包目录中,并且确实有一个名为 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\'”。只是没有 zip 文件。我所有的文件和目录都被解压了。所以我将文件压缩到一个名为 python37.zip 的存档中,这解决了导入错误。

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

            接下来我尝试的是在调用Py_Initialize() 之前使用Py_SetPath(L"C:/Work/build/product/Lib/site-packages")。这导致了

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

            我用这两个调用创建了一个最小的 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 中的特定路径。为了 例如,它可以是“/tmp/myimport.zip”,或者 '/tmp/myimport.zip/mydirectory',如果 mydirectory 是有效目录 档案馆内。如果“归档路径”,则会引发“ZipImportError” 不指向有效的 Zip 存档。的“存档”属性 zipimporter 对象包含目标压缩文件的名称。

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

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


            回答

            这可能是一个文档失败,而不是其他任何事情。不过,我们正在重新设计初始化,因此现在是提供此反馈的好时机。

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

            不存在的路径是可以的,那就是 zip 文件。您可以选择将stdlib压缩成一个zip,如果您将其命名为默认路径,它将自动找到,但您也可以将其解压缩并引用目录。

            全面了解嵌入比我准备在手机上输入的内容要多。希望这足以让您暂时继续前进。

            【讨论】:

              【解决方案14】:

              对于那些在Visual Studio 工作的人,只需将includeLiblibs 目录添加到Include DirectoriesLibrary DirectoriesProjects Properties -&gt; Configuration Properties &gt; VC++ Directories

              例如,我的系统上有Anaconda3 并使用Visual Studio 2015 这就是设置的样子(注意包含和库目录):

              编辑:

              正如bossi 所指出的,在您的用户Environment Variables 部分中设置PYTHONPATH 似乎是必要的。 示例输入可以是这样的(在我的情况下):

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

              似乎是必要的。

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

              还要注意:

              确保 PYTHONHOME 环境变量设置为 Python 你想使用的解释器。 Visual Studio 中的 C++ 项目依赖于 此变量用于定位文件,例如python.h,当 创建 Python 扩展。

              【讨论】:

                猜你喜欢
                • 2018-11-09
                • 1970-01-01
                • 2018-12-26
                • 2019-02-03
                • 2015-08-26
                • 1970-01-01
                • 2021-12-01
                • 1970-01-01
                • 2019-06-02
                相关资源
                最近更新 更多