有可能这仍然是一个问题,Pyinstaller和/或Folium的人没有兴趣修复它,但我会在这里再次发布,以防有人在那里发现了一个解决方法。
我有一个程序,可以创建地图,地理编码等,最近添加了folium包,以html格式创建一些交互式地图。我总是使用pyinstaller编译我的代码,以便我公司的其他人可以只使用可执行文件而不是运行python代码。如果我在IDE中运行我的代码,它会加载,运行并完全按预期执行。但是,当我尝试编译时,我在脚本中的某处有import folium
,在尝试运行pyinstaller创建的可执行文件时出错。
错误文本的内容如下:
Traceback (most recent call last):
File "analysisSuite.py", line 58, in <module>
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\natha\appdata\local\programs\python\python36-32\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
exec(bytecode, module.__dict__)
File "site-packages\folium\__init__.py", line 8, in <module>
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\natha\appdata\local\programs\python\python36-32\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
exec(bytecode, module.__dict__)
File "site-packages\branca\__init__.py", line 5, in <module>
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\natha\appdata\local\programs\python\python36-32\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
exec(bytecode, module.__dict__)
File "site-packages\branca\colormap.py", line 29, in <module>
File "site-packages\pkg_resources\__init__.py", line 1143, in resource_stream
File "site-packages\pkg_resources\__init__.py", line 1390, in get_resource_stream
File "site-packages\pkg_resources\__init__.py", line 1393, in get_resource_string
File "site-packages\pkg_resources\__init__.py", line 1469, in _get
File "c:\users\natha\appdata\local\programs\python\python36-32\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 479, in get_data
with open(path, 'rb') as fp:
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\natha\\AppData\\Local\\Temp\\_MEI309082\\branca\\_cnames.json'
[30956] Failed to execute script analysisSuite
我仍然是相对较新的Python,因此试图通过本文解读问题是非常压倒性的。我不知道是否有解决方法,我只需要编辑文件,添加文件或向pyinstaller添加一些参数,但也许其他人可以阅读此内容并了解可能导致此问题的原因。提前感谢任何有建议的人。
编辑:问题似乎与branca,这是folium的依赖。它查找site-packages \ branca文件夹中的_cnames.json文件,但要么没有按照它应该复制,要么我需要以某种方式在我的脚本中识别它应该查找这些文件然后只需手动复制他们进入我选择的文件夹。
附加更新:我一直在测试和测试,并确定了问题的核心。当您运行您的exe时,它会在临时文件夹中解压缩。 branca
中的一个模块是colormap.py
在colormap
文件中,基本上有三行可以使branca
无法正确加载。
resource_package = __name__
resource_path_schemes = '/_schemes.json'
resource_path_cnames = '/_cnames.json'
因此,当可执行文件在此临时文件夹中解压缩并且branca尝试加载时,由于上述这些行,它希望这两个文件也在此临时文件夹中,但当然,它们不会是因为它们是被告知总是只在colormap模块所在的文件夹中。这里的关键是找出一种方法,使路径引用可以是相对的,这样它就不会查看临时文件夹,而且引用也是动态的,所以无论你有可执行文件,只要你拥有那些json文件出现在它“知道”的某个文件夹中,那么你会很好。现在我只需要弄清楚如何做到这一点。
我有同样的问题。 Pyinstaller无法使用Python Folium包。由于Python 3.7和cx_Freeze的问题,我无法让你的cx_Freeze解决方案工作,但是在一天的压力下我发现了一个与社区共享的Pyinstaller解决方案。
首先,您必须编辑这3个文件:
进行以下更改,注释掉现有的ENV行并替换为以下代码:
#ENV = Environment(loader=PackageLoader('folium', 'templates'))
import os, sys
from jinja2 import FileSystemLoader
if getattr(sys, 'frozen', False):
# we are running in a bundle
templatedir = sys._MEIPASS
else:
# we are running in a normal Python environment
templatedir = os.path.dirname(os.path.abspath(__file__))
ENV = Environment(loader=FileSystemLoader(templatedir + '\\templates'))
在根文件夹中创建此spec文件,显然你的pathex和项目名称会有所不同:
# -*- mode: python -*-
block_cipher = None
a = Analysis(['time_punch_map.py'],
pathex=['C:\\Users\\XXXX\\PycharmProjects\\TimePunchMap'],
binaries=[],
datas=[
(".\\venv\\Lib\\site-packages\\branca\\*.json","branca"),
(".\\venv\\Lib\\site-packages\\branca\\templates","templates"),
(".\\venv\\Lib\\site-packages\\folium\\templates","templates"),
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='time_punch_map',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=True )
最后从终端使用此命令生成单个exe:
pyinstaller time_punch_map.spec
我无法使用pyinstaller工作。我不得不使用cx_Freeze。
pip install cx_Freeze
cx_Freeze要求创建setup.py文件,通常与要转换为exe的主脚本位于同一文件夹中。我的setup.py文件如下所示:
import sys
from cx_Freeze import setup, Executable
import os.path
PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')
# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {"packages": ["pkg_resources","asyncio","os","pandas","numpy","idna","folium","branca","jinja2","matplotlib"]}
# GUI applications require a different base on Windows (the default is for a
# console application).
base = None
if sys.platform == "win32":
base = "Win32GUI"
options = {
'build_exe': {
'include_files':[
os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'),
os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'),
# 'C:\\Users\\natha\\AppData\\Local\\Programs\\Python\\Python36-32\\Lib\\site-packages\\branca\\_cnames.json',
# 'C:\\Users\\natha\\AppData\\Local\\Programs\\Python\\Python36-32\\Lib\\site-packages\\branca\\_schemes.json'
],
},
}
setup( name = "MyProgram",
version = "0.1",
description = "MyProgram that I created",
options = {"build_exe": build_exe_options},
executables = [Executable("myProgram.py", base=base)])
注意我必须在“packages”字典中添加各种folium依赖项,例如branca,asyncio和pkg_resources。此外,我使用pip对asyncio,pkg_resources甚至setuptools进行了独立更新 - 例如:pip install --upgrade setuptools
一旦这些就位,我会从保存我的setup.py文件的目录打开一个命令提示符,然后输入python setup.py build
一旦运行,我的目录中有一个名为build
的新文件夹,里面是另一个文件夹,里面这是我的exe,完美运行。希望这有助于其他可能遇到此问题的人。