Il y a une chance que ce soit encore un problème et que les gens de Pyinstaller et / ou Folium n'aient aucun intérêt à le réparer, mais je le posterai à nouveau ici au cas où quelqu'un trouverait une solution de contournement.
J'ai un programme qui crée des cartes, des géocodes, etc. et a récemment ajouté le package folium pour créer des cartes interactives au format html. Je compile toujours mon code à l'aide de pyinstaller afin que les autres membres de mon entreprise puissent simplement utiliser l'exécutable plutôt que d'exécuter le code python. Si j'exécute mon code dans un IDE, il se charge, s'exécute et fonctionne exactement comme prévu. Cependant, lorsque j'essaie de compiler alors que j'ai import folium
quelque part dans mon script, j'obtiens une erreur en essayant d'exécuter l'exécutable créé par pyinstaller.
Le texte d'erreur lit quelque chose comme ceci:
resource_package = __name__ resource_path_schemes = '/_schemes.json' resource_path_cnames = '/_cnames.json'
Je suis encore relativement nouveau dans Python, donc essayer de déchiffrer le problème avec ce texte est assez écrasant. Je n'ai aucune idée s'il existe une solution de contournement, où je dois juste éditer un fichier, ajouter un fichier ou ajouter un paramètre à pyinstaller, mais peut-être que quelqu'un d'autre peut le lire et avoir une idée de ce qui pourrait causer ce problème. Merci d'avance à tous ceux qui ont des suggestions.
EDIT: Le problème semble être avec branca, qui est une dépendance de folium. Il recherche ce fichier _cnames.json qui se trouve dans le dossier site-packages \ branca mais soit n'est pas copié comme il se doit, soit j'ai besoin d'identifier d'une manière ou d'une autre dans mon script où il doit rechercher ces fichiers, puis simplement copier manuellement les dans un dossier que je choisis.
MISE À JOUR SUPPLÉMENTAIRE: J'ai testé et testé et j'ai déterminé le cœur du problème. Lorsque vous exécutez votre exe, il est décompressé dans un dossier temporaire. L'un des modules de branca
est colormap.py
Dans le fichier colormap
, il y a essentiellement trois lignes qui conservent branca code > de charger correctement.
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
Ainsi, lorsque l'exécutable est décompressé dans ce dossier temporaire et que branca essaie de se charger, à cause de ces lignes ci-dessus, il s'attend à ce que ces deux fichiers soient également dans cette temp dossier, mais bien sûr, ils ne le seront pas car on leur dit de toujours et uniquement d'être dans le dossier où se trouve le module de palette de couleurs. La clé ici est de trouver un moyen pour que la référence du chemin puisse être relative, afin qu'elle ne regarde pas dans le dossier temporaire mais aussi que la référence soit dynamique, de sorte que partout où vous avez votre exécutable, tant que vous les avez json présents dans un dossier dont il "connaît", alors vous serez bien. Maintenant, j'ai juste besoin de savoir comment faire cela.
3 Réponses :
Je n'ai pas pu faire fonctionner cela avec pyinstaller. J'ai dû utiliser à la place cx_Freeze.
pip install cx_Freeze
cx_Freeze nécessite qu'un fichier setup.py soit créé, généralement dans le même dossier que le script principal qui est converti en un exe. Mon fichier setup.py ressemble à ceci:
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)])
Remarquez que j'ai dû ajouter diverses dépendances folium au dictionnaire "packages", telles que branca, asyncio et pkg_resources. De plus, j'ai fait des mises à jour indépendantes pour asyncio, pkg_resources et même setuptools en utilisant pip - par exemple:
pip install --upgrade setuptools
Une fois ceux-ci en place, j'ouvrirais une invite de commande à partir du répertoire où mon fichier setup.py est enregistré et tapez simplement python setup.py build
Une fois que cela fonctionne, j'ai un nouveau dossier dans mon répertoire appelé build
et à l'intérieur de celui-ci se trouve un autre dossier, à l'intérieur duquel se trouve mon exe, qui fonctionnait parfaitement. J'espère que cela aidera quelqu'un d'autre qui pourrait rencontrer ce problème.
J'ai eu le même problème. Pyinstaller n'a pas pu fonctionner avec le package Python Folium. Je n'ai pas pu faire fonctionner votre solution cx_Freeze en raison de problèmes avec Python 3.7 et cx_Freeze mais avec un jour de stress j'ai trouvé une solution Pyinstaller que je partage avec la communauté.
Tout d'abord, vous devez éditer ces 3 fichiers:
\ folium \ folium.py
\ folium \ raster_layers.py
Apporte les modifications suivantes, en commentant la ligne ENV existante et en la remplaçant par le code ci-dessous:
pyinstaller time_punch_map.spec
Créez ce fichier de spécification dans votre dossier racine, évidemment votre chemin et le nom du projet seront différents:
# -*- 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 )
Enfin, générez l'exe unique avec cette commande depuis le terminal:
#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'))
p>
Cela a tout à fait du sens et j'ai l'impression que c'est proche, mais après sa construction, lorsque j'exécute l'exécutable, j'obtiens toujours la partie supérieure de l'erreur - liée à \ PyInstaller \ loader \ pyimod03_importers.py
Le problème de mise en œuvre que j'ai rencontré était dû à ma propre ignorance. @chinguetti votre méthode résout mes problèmes exécutables.
Avec pyinstaller, cela fonctionne en utilisant l'astuce ci-dessus. Si nous devons créer un dossier, ce fichier de script peut être utilisé.
import platform block_cipher = None a = Analysis(['Test_Beta.py'], pathex=['C:\\Old desktop\\test\\esky\\fileserver\\test11'], binaries=[(winsparkle, '.')], datas=[ ("C:\\Users\\kv\\AppData\\Local\\Continuum\\Anaconda3\\Lib\\site-packages\\branca\\*.json","branca"), ("C:\\Users\\kv\\AppData\\Local\\Continuum\\Anaconda3\\Lib\\site-packages\\branca\\templates","templates"), ("C:\\Users\\kv\\AppData\\Local\\Continuum\\Anaconda3\\Lib\\site-packages\\folium\\templates","templates"), ], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=['scipy', 'zmq', '_gtkagg', '_tkagg', 'bsddb', 'curses', 'pywin.debugger', 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl', 'Tkconstants', 'Tkinter'], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher) pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher) exe = EXE( pyz, a.scripts, [], exclude_binaries=True, name='Outview', debug=False, strip=False, upx=True, console=False ) coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name='Outview')