Создание исполняемых Zip-архивов с пакетами в проекте - PullRequest
2 голосов
/ 19 мая 2019

Мне кажется, что этот вопрос нуждается в лучшем названии, и я исправлю его, если кто-то предложит что-то лучшее.Проблема в том, что я не уверен в терминологии функции, которую я использую здесь.

Лучший способ описать мою проблему - показать, что я сделал.Проект находится здесь: https://github.com/jeffnyman/quendor

Этот проект настроен таким образом, что его можно выполнить как модуль.Например, из корня проекта кто-то может сделать это:

python3 -m quendor

У меня также есть скрипт сборки для создания почтового индекса в памяти (если я правильно использую эту терминологию):

https://github.com/jeffnyman/quendor/blob/master/build.py

Это работает в том случае, если вы запустите build.py, он сгенерирует файл quendor.py, который выполняет весь проект.Это работало нормально до тех пор, пока я не включил другие каталоги (например, мои utilities и zinterface).

С проектом, который сейчас находится в репо, если вы запустите сборку(.\build.py) и затем запустите сгенерированный файл:

./quendor.py

Вы получите следующую ошибку:

File "./quendor.py/quendor/__main__.py", line 6, in <module>
ModuleNotFoundError: No module named 'quendor.zinterface'

Итак, ключевой момент: , если все мои файлыв том же каталоге (т. е. в quendor) этот сценарий сборки отлично работает с точки зрения создания исполняемого файла сценария.

Но как только я включаю подкаталоги и файлы в эти каталоги, дела идут на югна меня с вышеуказанной ошибкой.

Я уверен, что все файлы собираются.Я обрабатываю это, начиная со строки 18 (https://github.com/jeffnyman/quendor/blob/master/build.py#L18). И если бы вы добавили в строку 24 это утверждение:

print(f"* {file_path}")

Вы бы увидели, что оно выдает следующее:

* quendor/__init__.py
* quendor/__version__.py
* quendor/zinterface/fileio.py
* quendor/utilities/messages.py
* quendor/__main__.py

Так что я подозреваю, что это может быть связано с кодом, в котором я пишу строку в строке 28 (https://github.com/jeffnyman/quendor/blob/master/build.py#L28). Я чувствую, что должен сделать больше, чтобы сообщить исполняемому файлу с zip-скриптом о модулях.

Но я не уверен, если (1) я точен и (2) даже если я точен, если это возможно. Я обнаружил, что я немного над головой здесь.

Будем благодарны за любые мысли, и я с удовольствием дополню их любыми разъяснениями или терминологией.

Ответы [ 3 ]

1 голос
/ 19 мая 2019

Так что я не буду комментировать, если у меня не будет больше репутации, но я смогу опубликовать ответ. Хотя у меня нет ответа, а есть комментарий. Я думаю, что вышеупомянутый комментарий не был предназначен для вашего фактического файла __main__.py, а скорее для того, который генерируется в вашем файле quendor.py. Возможно, вы захотите попробовать добавить операторы импорта в вашу упакованную строку, которую вы пишете.

Например, посмотрите, что произойдет, если в строке 32 вы добавите следующее: import quendor.zinterface.fileio as zio. (Не заменяйте строку, которая там есть. Просто поместите мою строку, а затем оставьте остальные.) Я не уверен, как работает процесс zip, но пытается ли он отразить процесс модуля, который должен работать. Однако, если это не так, это не сработает. Вы также можете просто попробовать сделать import quendor.zinterface. Само по себе это не сработает, но было бы интересно посмотреть, не выдало ли оно другую ошибку.

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

На самом деле, оказывается, я нашел способ сделать это! Требуется использовать os.walk вместо os.listdir. Это потребовало нескольких идей, которые люди обсуждали здесь. Вот скрипт, который делает трюк:

https://github.com/jeffnyman/quendor/blob/master/build.py

Вы можете сравнить это с моим предыдущим коммитом , который пытался справиться с этим другим способом.

Eldritch был прав, что я не мог просто сгладить каталог и не мог просто добавить импорт в строку, которую я записывал, в конечный zip-файл. Жан-Франсуа был прав, что я должен был сосредоточиться на генерируемом __main__.py. Мой вклад заключался в выяснении os.walk(), а затем параметризации записанной строки для обработки различных каталогов.

Наконец, это решение требует, согласно предложению HTF, чтобы я поместил пустой файл __init__.py в каждый пакет.

С моим решением вы можете запустить build.py, который затем генерирует скрипт quendor.py. Затем этот сценарий выполняется правильно с точки зрения распознавания импорта в различные пакеты.

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

Поигрывая практически со всеми вариантами импорта и сбора файлов, о которых я могу подумать в вашем репо, есть хорошие или плохие новости.

  • Плохая новость заключается в том, чтоответ таков: это невозможно.

  • Хорошая новость заключается в следующем: у вас есть работающая реализация, если вы просто храните все файлы в каталоге quendor вместо того, чтобы иметьподкаталоги.

Другая хорошая новость - вы наткнулись на что-то и создали проблему, которую гуру Python не могут ответить.И в этом есть определенное удовольствие!Я гарантирую, что вы не получите ответ на этот вопрос, который работает (за исключением решения «все файлы в одном каталоге»).

Уточнение ответа заключается в том, что если вы настраиваете программу для запуска от именимодуль в любом случае, просто используйте конфигурацию пипса.Это в основном делает то же самое, что вы хотите, но без необходимости выкручиваться.(Если нет причины, по которой вы выполняли сборку так, как использовали, а не использовали pip.)

...