Модуль Branca Python не может найти 2 важных файла json при запуске исполняемого файла, который использует folium - PullRequest
0 голосов
/ 23 февраля 2019

Есть вероятность, что это все еще проблема, и люди из 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, который является зависимостью от фолия.Он ищет тот файл _cnames.json, который находится в папке site-packages \ branca, но либо не копируется должным образом, либо, возможно, мне нужно как-то определить в моем скрипте, где он должен искать эти файлы, а затем просто скопировать вручнуюих в папку, которую я выбрал.

ДОПОЛНИТЕЛЬНОЕ ОБНОВЛЕНИЕ: Я тестировал и тестировал и определил суть проблемы.Когда вы запускаете свой exe, он распаковывается во временную папку.Один из модулей в branca - это colormap.py. В файле colormap, по сути, есть три строки, которые мешают правильной загрузке branca.

resource_package = __name__
resource_path_schemes = '/_schemes.json'
resource_path_cnames = '/_cnames.json'

Итак, когда исполняемый файл распаковывается в эту временную папку, и branca пытается загрузить его из-за этих строк, он ожидает, что эти два файла также будут находиться в этой временной папке, но, конечно,их не будет, потому что им всегда говорят, и они будут находиться только в папке, в которой находится модуль colormap.Ключевым моментом здесь является выяснение способа, чтобы ссылка на путь могла быть относительной, чтобы она не смотрела во временную папку, а также чтобы ссылка была динамической, чтобы везде, где у вас есть исполняемый файл, до тех пор, пока у вас есть эти.json файлы присутствуют в какой-то папке, о которой он «знает», тогда вы будете в порядке.Теперь мне просто нужно выяснить, как это сделать.

Ответы [ 2 ]

0 голосов
/ 04 мая 2019

У меня была такая же проблема.Pyinstaller не может работать с пакетом Python Folium.Я не смог заставить ваше решение cx_Freeze работать из-за проблем с Python 3.7 и cx_Freeze, но после напряженного дня я нашел решение Pyinstaller, которым я делюсь с сообществом.

Сначала вам нужно отредактировать эти 3 файла:

  1. \ folium \ folium.py

  2. \ folium \ raster_layers.py

  3. \ branca \ element.py

Вносит следующие изменения, комментируя существующую строку 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'))

Создайте этот файл спецификации в своей корневой папке, очевидно, ваш 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 )

Наконец, сгенерируйте одиночный исполняемый файл с этой командой из терминала:

pyinstaller time_punch_map.spec
0 голосов
/ 08 марта 2019

Я не мог заставить это работать, используя pyinstaller.Мне пришлось вместо этого использовать cx_Freeze.

pip install cx_Freeze

cx_Freeze требует создания файла setup.py, обычно в той же папке, что и основной скрипт, который преобразуется в исполняемый файл.Мой файл 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)])

Обратите внимание, что мне пришлось добавить различные зависимости от фолиума в словарь "пакетов", такие как branca, asyncio и pkg_resources.Кроме того, я сделал независимые обновления для asyncio, pkg_resources и даже setuptools, используя pip - например: pip install --upgrade setuptools

Как только они были созданы, я бы открыл командную строку из каталога, где находится мой файл setup.pyсохраните и просто наберите python setup.py build После того, как это запустится, у меня в каталоге будет новая папка build, и внутри нее находится еще одна папка, внутри которой находится мой exe-файл, который отлично работает.Надеюсь, что это поможет кому-то еще, кто может столкнуться с этой проблемой.

...