14

I want to call a function from a file in a sub folder. I would prefer do do it statically. I use empty __init__.py files as I've read that in simple cases they can be empty(and mine couldn't be an simpler) or that from 3.5 on I don't need them at all. But I am open to filling them.

I have the following file structure:

test
├── callfoo.py   (main)
├── __init__.py  (empty)
└── folder
    ├── submodule.py
    └── __init__.py (empty)

callfoo.py:

#import statement wanted

def main():
    foo()

if __name__ == "__main__":
        main()

submodule.py

def foo():
    print('foo')

For the import statement I've tried:

import test.folder.submodule
from test.folder import submodule
from test.folder.submodule import foo

each resulting in ModuleNotFoundError: No module named 'test.folder' I'm a bit confused here because they are taken straight from the Documentation

import .folder.submodule -> invalid syntax importlib.import_module('test.folder.submodule') ModuleNotFoundError: No module named 'test.folder'

This works:

import importlib.util
spec = importlib.util.spec_from_file_location("submodule", "/home/.../test/folder/submodule.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)

But I don't really want to do it dynamically especially not for several files.

This ModuleNotFoundError: No module named x deals with my error message but not with subfolders as far as I can tell (it works fine for me with submodule.py on the same level as callfoo.py)

There are several questions dealing with imports from sub folders but I couldn't make them work for me. I hope to have provided a dead simple problem formulation.

peer
  • 4,171
  • 8
  • 42
  • 73

1 Answers1

15

Let's suppose we have this folders/files architecture:

test
├── callfoo.py
└── folder
    ├── __init__.py
    └── submodule.py

1 directory, 3 files

callfoo.py:

from folder.submodule import foo

def main():
    foo()

if __name__ == '__main__':
    main()

submodule.py:

def foo():
    print('foo in submodule')

now place your self at the same level's folder of callfoo.py and run:

$ python3 callfoo.py

Output:

> foo in submodule
Chiheb Nexus
  • 9,104
  • 4
  • 30
  • 43
  • 1
    Thank you so much!!! Can you tell me why the [documentation](https://docs.python.org/3/tutorial/modules.html) (6.4) uses the top level package, in my case test? – peer Jan 06 '18 at 19:35
  • 1
    @peer in order to run the example in the documentation you need to set `sys.path` correctly. it says: `When importing the package, Python searches through the directories on sys.path looking for the package subdirectory.` – Chiheb Nexus Jan 07 '18 at 03:45
  • 1
    This works if you run python from the same directory as callfoo.py, but what if callfoo.py is part of a installed package, being imported from an arbitrary directory? – aaronsnoswell Jun 02 '18 at 04:03
  • this works at home for me but when i try it on the school computer it just says the module isn't found – Hippolippo Oct 03 '18 at 18:54
  • @Hippolippo check this [documentation link](https://docs.python.org/3.5/tutorial/modules.html#the-module-search-path) – Chiheb Nexus Oct 03 '18 at 23:58
  • 1
    @ChihebNexus I found out what the problem is, it was the way I was importing it that messed it up. – Hippolippo Oct 17 '18 at 18:34