My first post on here, bear with me.....
I'm working on bundling a tkinter application using PyInstaller, and I've come across an issue when I use the inspect library. Basically, I can call the source code of a class, but not a function, that I have written. I've made this contrived case to demonstrate:
I have a folder structure like this:
experiment/
---experiment.py
---init.py
---resources/
/---resources.py
/---init.py
---loader/
/---loader.py
/---init.py
resources.py defines one function an one class:
def foo(a):
print(str(a) + ' is what you entered.')
class Bar:
def __init__(self, b):
self.b = b
loader.py imports that function and that class and defines a function to print their source code:
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)
and experiment.py loads that printing function from loader.py and calls it:
from loader.loader import testfunc
testfunc()
I can run experiment.py in a Python console and get the expected output (source code for foo and Bar).
I then use PyInstaller to create an executable from experiment.py (from a virtual environment with just PyInstaller added). The spec file is untouched (I can share it), but I do copy/paste the loader and resources directories to dist/experiment so that the executable can find them. If I run experiment.exe from the Command Prompt, I get this output:
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
So the code for Bar is found and printed, but the code for foo cannot be found! Note that line 9 is where foo is inspected.
The real context is a graphing program where I want to return the code used to make a plot, in case users want to make tweaks. So foo is actually a lot of matplotlib code, loader is a module for formatting the plot code, and experiment is the tkinter application. As in this case, the inspect works fine from an IDE but breaks after building the exe.
More about my setup:
- the virtualenv was created with Anaconda Prompt; I used
conda createto make a new environment and thenpipinstalled PyInstaller - Python is 3.7.7
- everything in the environment, basically what it comes with:
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
- Windows 10 64bit
What I've tried:
- a lot of switching the import method (e.g. explicitly importing the function by name, using import *, importing only the module and using module.function)
- messing around with the
.specfile, like adding my modules to thedatasargument ofAnalysis. I've seen this issue, and I've tried to add my modules toa.pureas htgoebel commented, but I'm not sure if I'm doing this right, and it seems like maybe not the root issue since the code for the classBarcan be found from the same file - I've used both the most current PyInstaller version (3.6) and the current developer version from
https://github.com/pyinstaller/pyinstaller/archive/develop.zip
Overall the weirdest part seems that the class source code can be found but the function cannot, when they are in the same file - but maybe PyInstaller is making it more complicated than that in a way I don't understand? Please let me know if you have any suggestions or want me to try anything else. Happy to provide any other information/tests that I can. Cheers!