Razer
Razer

Reputation: 8201

Import module from subfolder

I want to import subfolders as modules. Therefore every subfolder contains a __init__.py. My folder structure is like this:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

In my main script I import

from dirFoo.foofactory import FooFactory

In this factory file I include the sub modules:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

If I call my foofactory I get the error, that python can't import the submodules foo1 and foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1

Upvotes: 151

Views: 248768

Answers (6)

user418615
user418615

Reputation: 11

just tested and this worked:

# create sub dir
mkdir ./modules

create module1.py

vim ./modules/module1.py

def hello():
    print("hello have a nice day")
    
def bye():
    print("bye")

vim write and quit

:wq

include module1.py functionality into fileA.py and call it's functions

vim ./fileA.py

#!/usr/bin/env python
import sys
sys.path.append('./modules')

print("===== testing modules =====")
import module1

# call functions of the module
module1.hello()
module1.bye()

Upvotes: 0

Abhijit Pritam Dutta
Abhijit Pritam Dutta

Reputation: 5581

Just create an empty __init__.py file and add it in root as well as all the sub directory/folder of your python application where you have other python modules. See https://docs.python.org/3/tutorial/modules.html#packages

Upvotes: 3

Vivek22
Vivek22

Reputation: 858

Just to notify here. (from a newbee, keviv22)

Never and ever for the sake of your own good, name the folders or files with symbols like "-" or "_". If you did so, you may face few issues. like mine, say, though your command for importing is correct, you wont be able to successfully import the desired files which are available inside such named folders.

Invalid Folder namings as follows:

  • Generic-Classes-Folder
  • Generic_Classes_Folder

valid Folder namings for above:

  • GenericClassesFolder or Genericclassesfolder or genericClassesFolder (or like this without any spaces or special symbols among the words)

What mistake I did:

consider the file structure.

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

What I wanted to do?

  • from testFile.py, I wanted to import the 'targetClass.py' file inside the Generic-Class-Folder file to use the function named "functionExecute" in 'targetClass.py' file

What command I did?

  • from 'testFile.py', wrote command, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Got errors like SyntaxError: invalid syntax

Tried many searches and viewed many stackoverflow questions and unable to decide what went wrong. I cross checked my files multiple times, i used __init__.py file, inserted environment path and hugely worried what went wrong......

And after a long long long time, i figured this out while talking with a friend of mine. I am little stupid to use such naming conventions. I should never use space or special symbols to define a name for any folder or file. So, this is what I wanted to convey. Have a good day!

(sorry for the huge post over this... just letting my frustrations go.... :) Thanks!)

Upvotes: 28

Rob Wouters
Rob Wouters

Reputation: 16327

There's no need to mess with your PYTHONPATH or sys.path here.

To properly use absolute imports in a package you should include the "root" packagename as well, e.g.:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

Or you can use relative imports:

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2

Upvotes: 199

Flavio Wuensche
Flavio Wuensche

Reputation: 10326

Say your project is structured this way:

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

Inside run.py, you can import scripts one and two by:

from subscripts import script_one as One
from subscripts import script_two as Two

Now, still inside run.py, you'll be able to call their methods with:

One.method_from_one(param)
Two.method_from_two(other_param)

Upvotes: 8

Max Kamenkov
Max Kamenkov

Reputation: 2598

Set your PYTHONPATH environment variable. For example like this PYTHONPATH=.:.. (for *nix family).

Also you can manually add your current directory (src in your case) to pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())

Upvotes: 12

Related Questions