I'm transitioning over some old scripts from python v2.7 to v3.6, and one of the things I want to do is have a package that can (a) be imported to expose inner workings to other scripts, but also (b) be runnable from the command line to run in typical ways.

In python2 this was not difficult -- I used both an __init__.py file (for importing) and a __main__.py file (for running). But in python3, this doesn't seem to work -- for example, take the minimal package:

minimal/
  __init.py__
  __main.py__
  func.py
  func2.py

__init__.py

from .func import f
from .func2 import add2

__main__.py

from func import f
f(1)

func.py

from .func2 import add2
def f(x):
  print(add2(x))

func2.py

def add2(x):
  return x + 2

If I open python and type import minimal this works just fine, but if from the command line I type python minimal/ I get the error:

ImportError: attempted relative import with no known parent package

This arises at line 1 of func.py, at the import of func2. If I instead remove the period from that line so it is instead from func2 import add2, then I can run python minimal/ from the command line just fine. But when I try to open python and run import minimal, at that same line I get the error:

ModuleNotFoundError: No module named 'func2'

I understand that the period is required for intra-package importing, but is there any way to make this work within the main script as well? Or another package structure that would allow both imports and running?

Change your project structure to:

minimal_cmd/
├── __main__.py
└── minimal
    ├── __init__.py
    ├── func.py
    └── func2.py

and do a fully qualified import in __main__.py:

if __name__ =='__main__':

    from minimal.func import f

    f(1)

Calling from the command line:

$ python minimal_cmd
3

and importing when minimal is the the current working directory or if the package is on the PYTHONPATH:

>>> import minimal
>>> minimal.f(2)
4
  • Does this work for you? – Mike Müller Sep 4 at 6:51
  • Sort of... it means I can't have a package that I can both run and import but seems like moving the main function out is the only workaround that seems to work. Thanks! – user2048508 Sep 4 at 14:18

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.