Как правильно включить внешние ресурсы с помощью cxfreeze?

Я пытаюсь использовать cxfreeze для создания своих сценариев Python в .exe файл. Однако мои сценарии используют некоторые внешние файлы данных, которые не упаковываются в созданный файл libary.zip.

Например, мои скрипты находятся в src/, а внешние данные — в src/data/. Я указал свойство include_files в build_exe_options, но это только копирует каталог и файлы в созданный каталог; он не добавляет их в library.zip, где сценарии в конечном итоге ищут файлы.

Даже если я захожу в созданный library.zip и вручную добавляю каталог data, я получаю ту же ошибку. Есть идеи, как заставить cxfreeze правильно упаковать эти внешние ресурсы?

setup.py

from cx_Freeze import setup, Executable

build_exe_options = {"includes" : ["re"], "include_files" : ["data/table_1.txt", "data/table_2.txt"]}

setup(name = "My Script",
      version = "0.8",
      description = "My Script",
      options = { "build_exe" : build_exe_options },
      executables = [Executable("my_script.py")])

fileutil.py (где он пытается прочитать файлы ресурсов)

def read_file(filename):
    path, fl = os.path.split(os.path.realpath(__file__))
    filename = os.path.join(path, filename)
    with open(filename, "r") as file:
        lines = [line.strip() for line in file]
        return [line for line in lines if len(line) == 0 or line[0] != "#"]

... звонил с ...

read_file("data/table_1.txt")

Отслеживание ошибок

Traceback (most recent call last):
  File "C:\Python33\lib\site-packages\cx_Freeze\initscripts\Console3.py", line 2
7, in <module> exec(code, m.__dict__)
  File "my_script.py", line 94, in <module>
  File "my_script.py", line 68, in run
  File "C:\workspaces\py\test_script\src\tables.py", line 12, in load_data
    raw_gems = read_file("data/table_1.txt")
  File "C:\workspaces\py\test_script\src\fileutil.py", line 8, in read_file
    with open(filename, "r") as file:
FileNotFoundError: [Errno 2] No such file or directory:
'C:\\workspaces\\py\\test_script\\src\\build\\exe.win32-3.3\\library.zip\\data/table_1.txt'

person asteri    schedule 03.09.2013    source источник


Ответы (1)


У меня работала следующая структура:

|-main.py
|-src
 |-utils.py (containing get_base_dir())
|-data

затем всегда обращайтесь к своим данным относительно местоположения main.py, которое вы получаете с помощью следующей функции в каталоге src:

import os, sys, inspect
def get_base_dir():
   if getattr(sys,"frozen",False):
       # If this is running in the context of a frozen (executable) file, 
       # we return the path of the main application executable
       return os.path.dirname(os.path.abspath(sys.executable))
   else:
       # If we are running in script or debug mode, we need 
       # to inspect the currently executing frame. This enable us to always
       # derive the directory of main.py no matter from where this function
       # is being called
       thisdir = os.path.dirname(inspect.getfile(inspect.currentframe()))
       return os.path.abspath(os.path.join(thisdir, os.pardir))

Если вы включите данные в соответствии с документацией cx_Freeze, они будут в той же директории, что и .exefile (т.е. не в zip-файле), что будет работать с этим решением.

person Felix Zumstein    schedule 03.09.2013
comment
Вот соответствующая часть документации: cx-freeze. readthedocs.org/en/latest/faq.html#using-data-files - person Thomas K; 04.09.2013