0

I am trying to better understand importing modules. I read about how to do this from here https://stackoverflow.com/a/14132912/14179793 and I can get it to work using solution 1. There is an additional variable that I need to figure out though.

This is a dummy project I am testing with:

.
├── a_package
│   ├── __init__.py
│   └── lib_a.py
├── b_package
│   ├── __init__.py
│   └── test_script.py
├── main.py
└── src
    └── src_lib
        └── src_lib.py

With this setup I can do:

python -m b_package.test_script
this is lib a function
This is src_lib_function.

test_script.py:

from a_package.lib_a import lib_a_function
from src.src_lib.src_lib import src_lib_function

if __name__ == '__main__':
    lib_a_function()
    src_lib_function()
    pass

The goal is to make b_package/test_script.py executable without using python test_script ie ./test_script

However, adding the shebang at the top #!/usr/bin/env python causes an import error:

$ ./b_package/test_script.py 
Traceback (most recent call last):
  File "./b_package/test_script.py", line 2, in <module>
    from a_package.lib_a import lib_a_function
ModuleNotFoundError: No module named 'a_package'

I assume it is because python is not loading it as a module based off the above mentioned question but I am not sure how to resolve this.

Cogito Ergo Sum
  • 592
  • 6
  • 18
  • 1
    A quick and dirty way to make it work is to add the root path of your tree to "sys.path" in your "test_script.py" before the import happens that causes the error. – Michael Butscher Dec 16 '21 at 23:38
  • 1
    Do you mind using setuptools for that? If so, I could describe that in answer. – kosciej16 Dec 16 '21 at 23:44
  • @kosciej16 I do not mind. I will say that this is a simplified example for a file structure I am having to work with. In b_package there are actually a large number of scripts that should be callable. – Cogito Ergo Sum Dec 17 '21 at 14:51

1 Answers1

2

I ended up using setuptools as suggested by kosciej16 to achieve the desired results.

New project structure:

.
├── a_package
│   ├── __init__.py
│   └── lib_a.py
├── b_package
│   ├── __init__.py
│   └── test_script.py
├── main.py
├── pyproject.toml
├── setup.cfg
└── src
    ├── __init__.py
    └── src_lib
        ├── __init__.py
        └── src_lib.py

setup.cfg:

[metadata]
name = cli_test
version = 0.0.1

[options]
packages = find:

[options.entry_points]
console_scripts =
    test_script = b_package.test_script:main

This allows the user to clone the repo and run pip install . from the top level then they can execute the script by just typing test_script

Cogito Ergo Sum
  • 592
  • 6
  • 18