Frage

I'm attempting to make a Pyinstaller build for Windows 7 using Pyinstaller 2.1. The module uses relative imports because the package is typically used in Linux as a 'regular' Python package. Is there a way to create a spec file to handle this type of setup? Ideally I would like to have a Python package that I can make a Pyinstaller exe with for Windows and have a 'regular' pip-installable Python package in Linux/OS X.

I was thinking of maybe using hidden imports or something to achieve this.

I've tried using the default Pyinstaller settings and pointing it at my 'main' python script. I get the following from the resulting exe:

'Attempted relative import in non-package'

This makes sense because I'm pointing Pyinstaller at my main.py file in the package and Pyinstaller is NOT picking up my entire package. This is just the starting point for using the module from the command-line. However, you can import it and use it in your own code as well.

Sidenote:

The reasoning is this package requires numpy and scipy. Yes, I know there are good ways to get these working in Windows with Anaconda, etc. However, I'm stuck with an exe setup now for legacy reasons.

War es hilfreich?

Lösung

I can't find a way to get Pyinstaller to do this. However, I don't think it's the fault of Pyinstaller. It's more of a problem with the way I structured my package.

I was passing a script to Pyinstaller that was a part of my package. The better way to do that would be to provide a simple Python script outside of the package that serves as the cli front-end to the package.

For example, consider a package layout like this (assume files use relative imports):

repo_dir/
    setup.py
    README.md
    package_a/
        main.py
        support_module.py
        __init__.py

My previous attempt was trying to build main.py by passing it to Pyinstaller. This resulted in the error mentioned in the above question.

However, I later added a cli.py script that does something like this:

from package_a.main import main
if __name__ == '__main__':
    main()

Now, I can pass cli.py to Pyinstaller and my explicit relative imports are only used inside of the package. So, it all works. Here's a sample directory layout that works just for reference:

repo_dir/
    setup.py
    cli.py
    README.md
    package_a/
        main.py
        support_module.py
        __init__.py

Andere Tipps

In my case, MacOS 12.x, I had some relative imports similar to this

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from utils import *

and I had a structure like this

dirA
 utils.py
 dirB
  my_app.py

and the created .app file didn't work. The problem was that I was running pyinstaller from w/in dirB, where, the utils.py module couldn't be found by pyinstaller. The solution was to specify any paths from which my_app.py imported modules. This is possible either explicitly w/ option/flag -p of pyinstaller or implicitly, by running pyinstaller from dirA and adding __init__.py(empty) in dirB. Adding the __init__.py "forces" pyinstaller to extend PYTHONPATH by dirA and not dirB.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top