Pyinstaller 找不到路径case

简介

python应用越来越广泛,有时需要将python的project打包成二进制,到一个没有安装python解释器的环境中执行。Pyinstaller对这个功能提供了较好的支持。

Pyinstaller能够在Windows、Linux、 Mac OS X 等操作系统下将 Python 源文件打包,通过对源文件打包, Python 程序可以在没有安装 Python 的环境中运行,也可以作为一个 独立文件方便传递和管理。

安装

$ pip install pyinstaller

异常复现

Babel (2.5.1)
PyInstaller (3.3)

代码:

# run.py
#!/usr/bin/env python
# encoding: utf-8

import babel

print babel.localedata.locale_identifiers()
$ pyinstall -F run.py
$ ./dist/run
Traceback (most recent call last):
  File "pktest/run.py", line 6, in <module>
  File "babel/localedata.py", line 76, in locale_identifiers
OSError: [Errno 2] No such file or directory: '/tmp/_MEISf3zGo/locale-data'
[100180] Failed to execute script run

解决

指定需要的data路径:

$ pyinstaller -F run.py --add-data $(your_python_path)/babel/locale-data/:locale-data

也可以直接编辑.spec文件指定data

a = Analysis(['run.py'],
             pathex=['$(your_code_path)/pktest'],
             binaries=[],
             datas=[('$(your_python_path)/babel/locale-data/', 'locale-data')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)

原因

pyinstaller 并非对所有的第三方库都能完美支持,参考支持的第三方库。其中,对babel的支持:

Fully supported, including “localedata” external data files (automatically handled).

不过Babel (2.5.1)已经没有localedata,而是用locale-data取代,并且在代码中对Pyinstaller做了兼容:

# babel/localedata.py

...

def get_base_dir():
    if getattr(sys, 'frozen', False) and getattr(sys, '_MEIPASS', None):
        # we are running in a |PyInstaller| bundle
        basedir = sys._MEIPASS
    else:
        # we are running in a normal Python environment
        basedir = os.path.dirname(__file__)
    return basedir

_cache = {}
_cache_lock = threading.RLock()
_dirname = os.path.join(get_base_dir(), 'locale-data')

...

当环境为Pyinstaller,重新定义了basedir。我们需要重新指定locale-data路径,或者:

def get_base_dir():
    return os.path.dirname(__file__)

总结

Pyinstaller是一个很方便的库,功能强大,但是并不能完美支持所有第三方库。另外对于包含中文字符的场景也需要特别注意。

你可能感兴趣的:(Python)