【问题标题】:build python script to single exe with pyinstaller使用 pyinstaller 将 python 脚本构建为单个 exe
【发布时间】:2018-09-20 01:23:30
【问题描述】:

我遇到以下错误:脚本名称 = prepareIncidentCountMail.py

Traceback (most recent call last):
  File "Alexa\prepareIncidentCountMail.py", line 52, in <module>
  File "site-packages\pandas\core\frame.py", line 683, in style
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "c:\users\avikumar\documents\learn\alexa\venv\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\pandas\io\formats\style.py", line 50, in <module>
  File "site-packages\pandas\io\formats\style.py", line 118, in Styler
  File "site-packages\jinja2\environment.py", line 830, in get_template
  File "site-packages\jinja2\environment.py", line 804, in _load_template
  File "site-packages\jinja2\loaders.py", line 113, in load
  File "site-packages\jinja2\loaders.py", line 234, in get_source
  File "site-packages\pkg_resources\__init__.py", line 1459, in has_resource
  File "site-packages\pkg_resources\__init__.py", line 1509, in _has
NotImplementedError: Can't perform this operation for unregistered loader type
[10536] Failed to execute script prepareIncidentCountMail

我在链接的帮助下使用熊猫风格:Change color of complete row in data frame in pandas

我看到样式正在使用 jinja2 导致上述错误。有没有办法挂钩这个错误或任何其他工具来将 python 脚本转换为单个可执行文件。

【问题讨论】:

    标签: python-3.x pandas pyinstaller


    【解决方案1】:

    我昨天使用 giumas 在这里所做的调整版本自己解决了这个问题:https://github.com/pyinstaller/pyinstaller/issues/1898

    问题不在于挂钩(这是我第一次尝试解决方案),而是 pandas 样式模块导入 jinja2 的事实,它使用“get_template”方法,而后者又使用 pkg_resources 模块。最后一个是问题,由于某种原因 pyinstaller 不能很好地与 pkg_resources 模块配合使用。

    解决方案:找到 pandas 的安装位置,然后转到类似

    C:\Users\UserName\AppData\Local\Programs\Python\Python36\Lib\site-packages\pandas\io\formats

    在格式文件夹中找到 style.py 文件并在您喜欢的文本编辑器中打开它。在 style.py 中向下滚动到第 118 行,您将在其中看到:

    template = env.get_template("html.tpl")
    

    将此行更改为:

    template = env.from_string("html.tpl")
    

    保存文件并重新运行 pyinstaller。当您尝试运行可执行文件时,它应该按预期执行,没有任何错误消息。

    希望对你有帮助。

    【讨论】:

    • 我无法通过将“get_template”更改为“from_string”来渲染我的数据框。所有会出现的将是文字字符串'html.tpl'。我认为这样做的原因是“from_string”方法使用它作为模板提供的字符串,并使用文件名作为模板。我添加了以下代码,它为我修复了它。 path = os.path.dirname(__file__) + "/templates/html.tpl" with open(path) as fin: data = fin.read() template = env.from_string(data)
    • 你把这段代码放在template = env.from_string("html.tpl")之前还是之后?
    【解决方案2】:

    以下内容不需要手动更改库代码。如果有人有时间,这可以作为对 pyinstaller 中官方 Jinja2 钩子的更改添加:

    import sys
    from jinja2.loaders import FileSystemLoader
    
    
    class PyInstallerPackageLoader(FileSystemLoader):
        """Load templates from packages deployed as part of a Pyinstaller build.  It is constructed with
        the name of the python package and the path to the templates in that
        package::
            loader = PackageLoader('mypackage', 'views')
        If the package path is not given, ``'templates'`` is assumed.
        Per default the template encoding is ``'utf-8'`` which can be changed
        by setting the `encoding` parameter to something else.  Due to the nature
        of eggs it's only possible to reload templates if the package was loaded
        from the file system and not a zip file.
        """
    
        def __init__(self, package_name, package_path="templates", encoding="utf-8"):
            # Use the standard pyinstaller convention of storing additional package files
            full_package_path = f"{sys._MEIPASS}/{package_name}/{package_path}"
            # Defer everything else to the FileSystemLoader
            super().__init__(full_package_path, encoding)
    
    
    def patch_jinja_loader():
        # patching the pandas loader which fails to locate the template when called from a pyinstaller build
    
        if getattr(sys, "frozen", False):
            import jinja2
    
            jinja2.PackageLoader = PyInstallerPackageLoader
    

    它基本上制作了一个看起来像 Pandas 尝试使用的 Jinja2 PackageLoader 的加载器,以便可以对其进行修补。事实上,它使用了 FileSystemLoader,这正是我们 pyinstaller 查找模板文件所需要的。

    上面需要在导入pandas之前运行。

    我也发布了这个解决方案on the GitHub issue

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-12
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      • 2019-03-20
      • 2021-09-25
      • 1970-01-01
      • 2017-09-01
      相关资源
      最近更新 更多