exe-file created by pyinstaller, not find self-defined modules while running
Asked Answered
J

4

19

I create two python files, and the directory/file relations is as follows:

mytest---
     |---mycommon.py
     |---myMainDir---
                     |----myMain.py

In mycommon.py:

def myFunc(a):
    ...

And in myMain.py:

import sys
sys.path.append(os.path.join(os.path.dirname(os.path.abspath('__file__')), '..'))
import mycommon.py
mycommon.myFunc("abc")

Then I created exe using pyinstaller:

pyinstall.py -F mytest\myMainDir\myMain.py

MyMain.exe is created, but when run, is tells that can not find mycommon module.

Jeminah answered 19/8, 2015 at 10:57 Comment(2)
import mycommon must be without the py suffixFurnishings
@andpei Yes, you are right, thanks. This is a mistake while handwriting. But the problem is not solved.Jeminah
P
35

PyInstaller's official manual describes this issue:

Some Python scripts import modules in ways that PyInstaller cannot detect: for example, by using the __import__() function with variable data, or manipulating the sys.path value at run time. If your script requires files that PyInstaller does not know about, you must help it.

It also suggests what should be done in such a case:

If Analysis recognizes that a module is needed, but cannot find that module, it is often because the script is manipulating sys.path. The easiest thing to do in this case is to use the --paths= option to list all the other places that the script might be searching for imports:

pyi-makespec --paths=/path/to/thisdir --paths=/path/to/otherdir myscript.py

These paths will be added to the current sys.path during analysis.

Therefore, please specify the --paths argument while building the application. The manual states that specifying the -p argument is equivalent:

-p dir_list, --paths=dir_list

Set the search path(s) for imported modules (like using PYTHONPATH). Use this option to help PyInstaller to search in the right places when your code modifies sys.path for imports. Give one or more paths separated by ; (under Windows) or : (all other platforms), or give the option more than once to give multiple paths to search.

Pigtail answered 21/8, 2015 at 15:22 Comment(5)
The path option looks like the first option to try, if you're not calling pyinstaller from the directory the entry point source file lies.Omnibus
Doesn't work for me please take a look at #53150250Irrespective
Very helpful answer.Mute
Not helpful, tried to follow this answer, no luckPeregrinate
This is not a solution, because the argument to "sys.path.append" is based on the "os.getcwd()" which is done at run time in the script (how else would we know where to find "common"?). There is no way to know what to pass to --paths because it could change depending on the user's own directory structure.Undertone
M
3

Also I had to fight a bit to get pyinstaller correctly import python scripts in a subfolder where the path to the subfolder was set relatively via sys.path.insert.

The answer by Yoel was correct for me but I needed careful setting of paths in Windows. Here is what I did:

My main py is:

D:\_Development\pCompareDBSync\pCompareDBSync\pCompareDBSync.py

My imported py is:

D:\_Development\pCompareDBSync\pCompareDBSync\py\pCompareNVR.py

(I have many of such imported py's in folder .\py\ but here i just use a single one as example)

So my main PY, I have the following include:

sys.path.insert(0, 'py')

try:
    from pCompareNVR import fgetNV_sN_dict
    from pCompareNVR import findNVRJobInDBSync
    from pCompareNVR import getNVRRecords
    from pCompareNVR import saveNVRRecords
    from pCompareNVR import compareNVRs
except Exception as e:
    print('Can not import files:' + str(e))
    input("Press Enter to exit!")
    sys.exit(0)
pyinstaller --onefile pCompareDBSync.py 

-> pCompareDBSync.exe that did NOT include py/pCompareNVR.py

I had to include the absolute pad to the main PY and the imported PY's:

pyinstaller --onefile --paths=D:\_Development\pCompareDBSync\pCompareDBSync\ --paths=D:\_Development\pCompareDBSync\pCompareDBSync\py pCompareDBSync.py

-> pCompareDBSync.exe that did now include py/pCompareNVR.py -> OK

And that solved this issue for me!

Mellifluous answered 11/1, 2019 at 3:14 Comment(1)
Won't this make your executable actually execute stuff that are not... itself? And execute your development env? I mean, what happens if you try to execute it on a different machine? If that's the case, please delete your post (it leads to a dangerous leak and makes people lose time and puts them in danger).Highpriced
I
0

I am having the same issue as OP (and as this comes up a lot in google searches I though I would add my experience).

Similar folder layout, save for a common folder containing mycommon.py in the same location. I am running PyInstaller from myMainDir as part of a CI build step.

I had tried the suggested solutions: setting --paths, declaring the hidden imports in the spec file etc. I still could not get it working.

I ended up 'solving' (read hacking) the problem by adding a step in the build script to copy the common folder into myMainDir before running PyInstaller.

Indian answered 4/8, 2021 at 8:2 Comment(0)
S
0

Been trying to find a solution all over the internet. The thing is, maybe your application is like mine changing the directory after it fires up, therefore you need to change the directory back to where the application locates. use import os \n os.chdir("path/to/your/project") place that code at the beginning of your script (main function), it should work.

Shaikh answered 3/11, 2023 at 6:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.