Мой первый пост здесь, потерпите меня .....
Я работаю над сборкой приложения tkinter с помощью PyInstaller, и я столкнулся с проблемой при использовании inspect
библиотека. По сути, я могу вызвать исходный код класса, но не функцию, которую я написал. Я сделал этот надуманный пример, чтобы продемонстрировать:
У меня есть структура папок, подобная этой:
experiment/
---experiment.py
---init.py
---resources/
/---resources.py
/---init.py
---loader/
/---loader.py
/---init.py
resources.py
определяет одну функцию в одном классе:
def foo(a):
print(str(a) + ' is what you entered.')
class Bar:
def __init__(self, b):
self.b = b
loader.py
импортирует эту функцию и этот класс и определяет функцию для печати их исходного кода:
import inspect
from resources import resources
def testfunc():
source_Bar = inspect.getsource(resources.Bar)
print(source_Bar)
source_foo = inspect.getsource(resources.foo)
print(source_foo)
и experiment.py
загружает эту функцию печати из loader.py
и вызывает ее:
from loader.loader import testfunc
testfunc()
Я могу запустить experiment.py
в консоли Python и получить ожидаемый результат (исходный код для foo
и Bar
).
Затем я использую PyInstaller для создания исполняемого файла из experiment.py
(из виртуальной среды с добавлением только PyInstaller). Файл spec
не тронут (я могу поделиться им), но я копирую / вставляю каталоги loader
и resources
в dist/experiment
, чтобы исполняемый файл мог их найти. Если я запускаю experiment.exe
из командной строки, я получаю следующие выходные данные:
C:\Users\earne\Desktop\experiment\dist\experiment>experiment.exe
class Bar:
def __init__(self, b):
self.b = b
Traceback (most recent call last):
File "experiment\experiment.py", line 3, in <module>
File "experiment\loader\loader.py", line 9, in testfunc
File "inspect.py", line 973, in getsource
File "inspect.py", line 955, in getsourcelines
File "inspect.py", line 786, in findsource
OSError: could not get source code
[14188] Failed to execute script experiment
Таким образом, код для Bar
найден и напечатан, но код для foo
не найден ! Обратите внимание, что в строке 9 проверяется foo
.
Реальный контекст - это графическая программа, в которой я хочу вернуть код, использованный для построения графика, на случай, если пользователи захотят внести изменения. Так что foo
на самом деле много matplotlib
кода, loader
- это модуль для форматирования кода, а experiment
- приложение tkinter
. Как и в этом случае, inspect
отлично работает из IDE, но ломается после сборки exe.
Подробнее о моей настройке:
- virtualenv был создан с помощью Anaconda Prompt; Я использовал
conda create
, чтобы создать новую среду, а затем pip
установил PyInstaller - Python - это 3.7.7
- все в этой среде, в основном то, с чем она поставляется:
altgraph 0.17
certifi 2020.4.5.1
future 0.18.2
pefile 2019.4.18
pip 20.0.2
pyinstaller 4.0.dev0+03d42a2a25
pywin32-ctypes 0.2.0
setuptools 46.1.3.post20200330
wheel 0.34.2
wincertstore 0.2
Что я пробовал:
- много переключения метода импорта (например, явный импорт функции по имени, используя import *, импортируя только модуль и используя module.function)
- возиться с файлом
.spec
, как добавление моих модулей в аргумент datas
Analysis
, Я видел эту проблему , и я пытался добавить свои модули в a.pure
, как прокомментировал htgoebel, но я не уверен, что я делаю это правильно, и кажется, что, возможно, нет проблема root, поскольку код для класса Bar
можно найти в одном и том же файле - Я использовал как самую последнюю версию PyInstaller (3.6), так и текущую версию разработчика от
https://github.com/pyinstaller/pyinstaller/archive/develop.zip
В целом самая странная часть кажется, что исходный код класса может быть найден, но функция не может , когда они находятся в одном файле - но, возможно, PyInstaller делает это более сложным, чем это таким образом, я не понимаю? Пожалуйста, дайте мне знать, если у вас есть какие-либо предложения или хотите, чтобы я попробовал что-нибудь еще. Рад предоставить любую другую информацию / тесты, которые я могу. Ура!