четверг, 23 апреля 2015 г.

Python: как обойти ошибку cx_freeze при сборке с модулем obspy

Попытка сборка на ОС Windows заканчивается ошибкой при выполнении программы "Import error: could not load shared library from obspy.signal". Я расскажу как быстро преодолеть эту ошибку.

Obspy динамически подгружает pyd модули в obspy/signal/headers.py:27-28 и 49-50. Причем происходит формирование относительного пути до них, переходя на 1 уровень вверх в директорию Lib. Проблема в том что cx_freeze об этих pyd файлах заранее не знает, поэтому и не включает их при сборке. Если мы зададим в конфигурационном файле включения этих файлов, то не получим желаемый результат. Потому что headers.py рассчитывает их найти в ../Lib, а файлы копируются в корень сборочной директории build, что на несколько уровней выше ожидаемого. Как правильно разрешить этот конфликт я не знаю, поэтому пошел по пути быстрого, но не элегантного решения.

1. Сделаем себе копию файла headers.py и поместим в директорию проекта.

2. Сделаем две замены

C.CDLL(os.path.join(os.path.dirname(__file__), os.pardir, 'lib', lib_name + lib_extension))
на
C.CDLL(os.path.join(os.path.dirname(__file__), os.pardir,os.pardir,os.pardir, 'lib', lib_name + lib_extension))

3. Запишем файл setup.py следующим образом

from cx_Freeze import setup, Executable
import os,shutil
#my_hack
os.rename(r'C:\Python27\Lib\site-packages\obspy\signal\headers.py', r'C:\Python27\Lib\site-packages\obspy\signal\headers.py.backup')
shutil.copy('headers.py', r'C:\Python27\Lib\site-packages\obspy\signal/')


# Dependencies are automatically detected, but it might need
# fine tuning.
buildOptions = dict(packages = ['numpy','obspy','obspy.signal','scipy','matplotlib.backends.backend_tkagg'], include_files=[r'C:\Python27\Lib\site-packages\obspy\lib'], excludes = [])

import sys
base = 'Win32GUI' if sys.platform=='win32' else None

executables = [
Executable('calcsi_gui.py', base=base)
]

setup(name='calcsi_gui',
version = '1.0',
description = '',
options = dict(build_exe = buildOptions),
executables = executables)

#release my hack

os.remove(r'C:\Python27\Lib\site-packages\obspy\signal\headers.py')
os.rename(r'C:\Python27\Lib\site-packages\obspy\signal\headers.py.backup', r'C:\Python27\Lib\site-packages\obspy\signal\headers.py')

Жирным выделены необходимые правки. Фактически на время сборки будет происходить подмена оригинального headers.py на модифицированный.

0 коммент.:

Отправить комментарий