12

I have a python program that is entirely contained in a directory with the following structure:

myprog/
├── __init__.py
├── __main__.py
├── moduleone.py
└── moduletwo.py

I would like to be able to package this and distribute it so that another developer can do pip install -e /path/to/git/clone/of/myprog and can then import myprog in his own programs and do cool stuff with it.

I would also like to be able to run myprog at the command line as follows:

PROMPT> python myprog

When I do this, I expect python to execute the __main__.py module, which it does. However, this module makes references to some functions that are declared in __init__.py and which need to be available both when the program is run at the command line and when it is imported by another program. However, I'm getting the following error:

NameError: name 'function_you_referenced_from_init_file' is not defined

Do I have to import these functions into __main__.py somehow?

I tried a simple example as follows:

PROMPT> cat myprog/__init__.py
def init_myprog():
    print 'running __init__.init_myprog()'

PROMPT> cat myprog/__main__.py
import myprog
print 'hi from __main__.py'
myprog.init_myprog()

PROMPT> ls -l myprog
total 16
-rw-r--r--  1 iit    63B Aug 30 11:40 __init__.py
-rw-r--r--  1 iit    64B Aug 30 12:11 __main__.py

PROMPT> python myprog
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/Users/jon/dev/myprog/__main__.py", line 1, in <module>
    import myprog
ImportError: No module named myprog
tadasajon
  • 14,276
  • 29
  • 92
  • 144
  • 4
    To whoever is voting to close the question -- if it's that stupid and simple, maybe you could just explain it to me in a couple of seconds? I tried to learn from this link http://stackoverflow.com/questions/3411293/using-modules-own-objects-in-main-py but am still having trouble. – tadasajon Aug 30 '13 at 16:29
  • You have to import everything except builtins, so the answer is a pretty obvious "yes". – Lennart Regebro Aug 30 '13 at 16:36

3 Answers3

15

The __init__.py is only loaded when you are import the package. You are instead treating the directory as a script, by executing the directory.

You can still treat the package as a script, instead of the directory however. To both treat the directory as a package and as the main script, by using the -m switch:

python -m myprog
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I tried that, and now get a `No module named myprog`. [This answer](http://stackoverflow.com/questions/16637428/relative-import-in-python-3-not-working#33195094) seems to indicate that treating a directory as a package *and* a script are bad practice. Thoughts? – Jens Nov 24 '15 at 01:59
  • The answer states a personal opinion. Several standard library modules, plus popular packages such as `virtualenv` and `pip` support being run as a script. I personally appreciate and use this functionality. If you are getting a *No module named Foo* error your module can't be imported either; are you sure it is available on your Python path? – Martijn Pieters Nov 24 '15 at 07:34
10

Do I have to import these functions into __main__ somehow?

Yes. Only items in builtins are available without an import. Something like:

from myprog import func1, func2

should do the trick.

If you don't have myprog installed in the normal python path then you can work around it with something like:

import sys
import os
path = os.path.dirname(sys.modules[__name__].__file__)
path = os.path.join(path, '..')
sys.path.insert(0, path)
from myprog import function_you_referenced_from_init_file

Which, quite frankly, is horrid.

I would suggest going with MartijnPieters suggestion and put the -m on the command line, in which case __main__.py can look like:

from myprog import function_you_referenced_from_init_file
Community
  • 1
  • 1
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
  • This looks great, but it doesn't work on my machine. I have tried two or three different variations of importing and I always get "ImportError: No module named myprog" – tadasajon Aug 30 '13 at 16:14
  • @JonCrowell: Then you don't have the myprog module installed, so Python doesn't find it. Look at packaging and developing: http://guide.python-distribute.org/ http://www.scotttorborg.com/python-packaging/ Quick hack: Add the directory above myprog to PYTHOPATH. – Lennart Regebro Aug 30 '13 at 16:34
3

So, having looked at the other responses and not being thrilled, I tried:

from __init__ import *

from my __main__.py file.

I suppose it doesn't allow you to refer to the module by name, but for simple cases it seems to work.

Joey B
  • 31
  • 3