Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make PyInstaller's .spec files actually portable? (woes absolute path for 'pathex' parameter)

The PyInstaller .spec file is mean to be portable across the three platforms that it supports: Windows, Mac OS X and Linux.

I find it much easier to generate the .spec file once and modify it at will before building an executable from it.

In every example on the Internet (e.g. this one), the .spec file would always define an absolute path in for the pathex parameter in the ANALYSIS section. This makes the build non-portable, because the absolute path is not only specific to the machine the build runs on, but also the platform.

Does this always have to be an absolute path or is there a way to make it completely portable?

like image 308
fatuhoku Avatar asked Oct 23 '13 15:10

fatuhoku


People also ask

How do I add paths to PyInstaller?

Add the path for the 'pyinstaller.exe' to your Windows environment variables. Open a instance of File Explorer and navigate to C:\Program Files\Python37\Scripts or C:\Users\USER_NAME\AppData\Roaming\Python\Python37\Scripts and look for the executable. Once you find the file make sure to get its full path.

Where is the PyInstaller path?

After installation, the pyinstaller binary is located in your virtual environment's bin/ directory, or where your Python executable is located. If that directory isn't in your PATH , include the whole path when you run pyinstaller .

What is Pathex in PyInstaller?

pathex : a list of paths to search for imports (like using PYTHONPATH ), including paths given by the --paths option. binaries : non-python modules needed by the scripts, including names given by the --add-binary option; datas : non-binary files included in the app, including names given by the --add-data option.

How do I get the Python application path?

getcwd() method to get Python Script location. The os. getcwd() method is used for getting the Current Working Directory in Python. The absolute path to the current working directory is returned in a string by this function of the Python OS module.


2 Answers

If you place the .spec file in its default location you can simply remove pathex from the spec because 'current directory' and 'your-configured-pathex-here' are identical.

Explanation

pathex is an optional list of paths to be searched before sys.path

Source: https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/building/build_main.py#L123

The spec file is actually executable Python code. PyInstaller builds the app by executing the contents of the spec file.

Source: https://github.com/pyinstaller/pyinstaller/blob/develop/doc/spec-files.rst#using-spec-files

This leads to the conclusion that you should be able either hardcode each path for the three environments like so

pathex=["/Users/fatuhoku/Python/myapp", "C:\\Python\\myapp", "/home/fatuhoku/Python/myapp"],

or call a handwoven Python function that just returns a list with a single element that is the current working directory.

If you run PyInstaller it tells you something like this:

46 INFO: Extending PYTHONPATH with paths
['current directory', 'your-configured-pathex-here']
like image 182
Marcel Stör Avatar answered Oct 09 '22 07:10

Marcel Stör


As others have pointed out, the .spec file is Python code. What you want is for pathex to be an absolute path on the machine currently executing the code. You can do this with the help of the SPECPATH global variable that is defined within the .spec file. (See all available globals listed in the PyInstaller docs here.)

In our case, I used:

import os

spec_root = os.path.abspath(SPECPATH)

...

pathex=[spec_root]

If your .spec is not in the same directory as your package/script, you can use os.path.abspath(os.path.join(SPECPATH, '..')) or something similar to find your pathex from your spec file.

like image 23
Juan Avatar answered Oct 09 '22 06:10

Juan