Distributing a script with few modules

What is the best way of distributing a Python script with few pure-python modules? All this should be easy to install to a system without pip and venv. Ideally by just copying or extracting few text files and directories.

Currently I put the script to a bin directory available in my PATH and in the same directory I create lib_python sub-directory for storing the library modules.

In my script I currently use:

import os
import sys
# my other regular imports

lib_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib_python')
sys.path.insert(0, lib_dir)

# my imports from the distributed modules:
# pylint: disable=wrong-import-position
import my_namespace.my_library   # noqa: E402

This way seems to be useable so far. There are few drawbacks though:

  • Not all imports are at the beginning of the file. I have to use linter directives to silence the complains.
  • Linters and/or language servers can have problems with imports from dynamic locations like that.
  • A directory name defined by Python standards would be much better instead of inventing my own.

Additional thoughts:

  • For simplicity I would like to avoid using wrapper scripts to start my scripts. But if you can convince me that this way is better I will accept that :slight_smile:
  • I do not want to edit the files (for example to add the current path of the library directory) as part of the installation.
  • I can imagine there could be problems when one library module needs to use another library module.

If I were in your situation, I think I would look into a zipapp based solution, maybe with the help of pex or shiv.

1 Like

Thank you for the tip! I will look into that. I have to decide if it is worth to not have the python files directly accessible (to tune them if needed).

The Python programs are really scripts with some parameters defined as constants inside them… Also I do not develop the scripts on the target platform because I do not have (and cannot have) the developer tools there so sometimes I need to make a small modification on the target platform.

Can you use the ~/.local/bin and ~/.local/lib/pythonx.x folders?
You would need to put ~/.local/bin on the PATH if its not already there.

One way is distributing egg or wheel files. A user can import the package as follows:

import sys
import os
sys.path.append(os.path.abspath("xxxlib-0.0.0-py3.10.egg"))
# or
sys.path.append(os.path.abspath("xxxlib-0.0.0-py3-none-any.whl"))

or the user can install the package by pip install *.whl.

Note that you can not import .pyd from egg / whl.
(see Cannot import pyd from egg)