520

I have a file called tester.py, located on /project.

/project has a subdirectory called lib, with a file called BoxTime.py:

/project/tester.py
/project/lib/BoxTime.py

I want to import BoxTime from tester. I have tried this:

import lib.BoxTime

Which resulted:

Traceback (most recent call last):
  File "./tester.py", line 3, in <module>
    import lib.BoxTime
ImportError: No module named lib.BoxTime

Any ideas how to import BoxTime from the subdirectory?

EDIT

The __init__.py was the problem, but don't forget to refer to BoxTime as lib.BoxTime, or use:

import lib.BoxTime as BT
...
BT.bt_function()
martineau
  • 99,260
  • 22
  • 139
  • 249
Adam Matan
  • 107,447
  • 124
  • 346
  • 512

11 Answers11

602

Take a look at the Packages documentation (Section 6.4).

In short, you need to put a blank file named

__init__.py

in the lib directory.

Phan Nhat Huy
  • 806
  • 2
  • 9
  • 23
Greg
  • 5,486
  • 3
  • 19
  • 19
  • 65
    Why does it feel *hacky*? It's the way python marks safe/available import directories. – IAbstract Aug 26 '14 at 16:52
  • 11
    Not only it marks safe/available import directories, but also provides a way to run some initialization code when importing a directory name. – Sadjad Nov 05 '14 at 10:26
  • 37
    Yes this is hacky and even dirty, and in my opinion the language shouldn't impose its way of loading files across the filesystem. In PHP we solved the problem by letting the userland code register multiple autoloading functions that are called when a namespace/class is missing. Then the community has produced the PSR-4 standard and Composer implements it, and nowadays nobody has to worry about that. And no stupid hardcoded `__init__` files (but if you want it, just register an autoloading hook ! This is the difference between _hacky_ and _hackable_). – Morgan Touverey Quilling Oct 07 '15 at 11:15
  • 1
    @YaShChaudhary It didn't work for me until I changed the reference to library: foldername.modulename – mimic Jul 23 '18 at 22:29
  • @mimic Your foldername.modulename worked for me doing an explict dynamic load with importlib.import_module. – Guerry Aug 09 '19 at 20:45
  • 1
    The necessary `__init__.py` file was at least not comfortable, may it be hacky or not. And this point got resolved in Python 3.3: A package can be made up without the file. – MasterControlProgram Oct 23 '19 at 11:53
  • See also https://stackoverflow.com/questions/37139786/is-init-py-not-required-for-packages-in-python-3-3 – Étienne Jan 28 '20 at 10:48
  • @IAbstract `always has been`... – F8ER Apr 29 '21 at 05:54
193
  • Create a subdirectory named lib.
  • Create an empty file named lib\__init__.py.
  • In lib\BoxTime.py, write a function foo() like this:

    def foo():
        print "foo!"
    
  • In your client code in the directory above lib, write:

    from lib import BoxTime
    BoxTime.foo()
    
  • Run your client code. You will get:

    foo!
    

Much later -- in linux, it would look like this:

% cd ~/tmp
% mkdir lib
% touch lib/__init__.py
% cat > lib/BoxTime.py << EOF
heredoc> def foo():
heredoc>     print "foo!"
heredoc> EOF
% tree lib
lib
├── BoxTime.py
└── __init__.py

0 directories, 2 files
% python 
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from lib import BoxTime
>>> BoxTime.foo()
foo!
serv-inc
  • 29,557
  • 9
  • 128
  • 146
hughdbrown
  • 42,826
  • 20
  • 80
  • 102
78

You can try inserting it in sys.path:

sys.path.insert(0, './lib')
import BoxTime
Kresimir
  • 2,454
  • 1
  • 17
  • 13
  • 14
    This is great if you for some reason can't or won't create the __init__.py file. – jpihl Mar 19 '14 at 08:29
  • 1
    It works if you run python from the "project" directory. The "." is interpreted relative to your current working directory, not relative to the directory where the file you're executing lives. Say you `cd /data`, `python ../project/tester.py`. Then it won't work. – morningstar Dec 27 '14 at 20:56
  • 2
    This worked for me. I prefer this over an *init*.py file, it makes for cleaner import statements. – Taylor Evanson Mar 19 '15 at 21:42
  • 6
    This works MUCH better and is the "correct" solution. __init__.py messes up packages like boto that have their own child folders with modules. – Dave Dopson Jul 03 '15 at 00:47
  • 1
    @jpihl You have to create (at least) a empy file named ***__init__.py*** to allow python import modules from that folder. I've tried that solution and works perfectly (v2.7.6). – m3nda Aug 28 '15 at 00:44
  • This solution works when you are not running an app in the parent folder of the modules you are trying to import and when you don't have the `__init__.py` in the module folders. – A Star Oct 03 '17 at 00:14
  • @minsk You didn't, by any chance, happen to change the path AFTER attempting the import, instead of before? (I did at first, simply from old habit of beginning with imports.) – Magnus Gustavsson Mar 09 '18 at 13:04
  • A hint if you please, when in troubles with relative path as mentioned by @morningstar run it like: sys.path.append(sys.path[0] + '/lib') – Mikhail Zakharov Apr 28 '20 at 11:16
38

I am writing this down because everyone seems to suggest that you have to create a lib directory.

You don't need to name your sub-directory lib. You can name it anything provided you put an __init__.py into it.

You can do that by entering the following command in a linux shell:

$ touch anything/__init__.py 

So now you have this structure:

$ ls anything/
__init__.py
mylib.py

$ ls
main.py

Then you can import mylib into main.py like this:

from anything import mylib 

mylib.myfun()

You can also import functions and classes like this:

from anything.mylib import MyClass
from anything.mylib import myfun

instance = MyClass()
result = myfun()

Any variable function or class you place inside __init__.py can also be accessed:

import anything

print(anything.myvar)

Or like this:

from anything import myvar

print(myvar)
nurettin
  • 9,834
  • 5
  • 53
  • 77
  • My folder structure is `utils\__init__.py` and `utils\myfile.py`. (Utils contain both files) This is how I am trying to import `from utils.myfile import myMethod`. But I get `ModuleNotFoundError: No module named 'utils'`. What could be wrong? **P.S:** I am using `Django` and trying to import in `views.py` which is at the same level as `utils` folder – Jagruti Mar 18 '19 at 08:16
  • It is possible to use absolute paths when importing modules and run your program with `PYTHONPATH=. python path/to/program.py` – nurettin Dec 10 '19 at 19:35
20

Does your lib directory contain a __init__.py file?

Python uses __init__.py to determine if a directory is a module.

Wade
  • 998
  • 6
  • 9
18

Try import .lib.BoxTime. For more information read about relative import in PEP 328.

drrlvn
  • 7,534
  • 2
  • 39
  • 56
  • 2
    I don't think I've ever seen that syntax used before. Is there strong reason (not) to use this method? – tgray Aug 11 '09 at 18:53
  • 2
    Why wasn't this the answer. Sure, if you want to do the whole packages thing, you should do that. But that's not what the original question was. – Travis Griggs Jan 29 '14 at 17:53
  • This gives me: ValueError: Attempted relative import in non-package – Alex Mar 07 '14 at 07:51
  • 6
    This only works if the file you're importing from is itself part of a package. If not, you'll receive the error that @Alex pointed out. – Jonathon Reinhart Apr 22 '15 at 23:58
14

Full example included

This basically covers all cases (make sure you have __init__.py in relative/path/to/your/lib/folder):

import sys, os
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/your/lib/folder")
import someFileNameWhichIsInTheFolder
...
somefile.foo()

Example:

You have in your project folder:

/root/myproject/app.py

You have in another project folder:

/root/anotherproject/utils.py
/root/anotherproject/__init__.py

You want to use /root/anotherproject/utils.py and call foo function which is in it.

So you write in app.py:

import sys, os
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../anotherproject")
import utils

utils.foo()
Mercury
  • 4,795
  • 1
  • 28
  • 40
  • 2
    if you're using `os.path` you probably want to use `os.path.join((os.path.dirname(os.path.realpath(__file__)),'..','anotherproject')` instead of hardcoding the '/' in your path concatenation. – cowbert Nov 15 '17 at 02:58
  • Why can't you just do `"../anotherproject"` without the `os.path.dirname()`? – Moshe Rabaev Jul 30 '18 at 22:46
  • @MosheRabaev - It is good practice to use os.path functions. In case of wrting "../anotherproject" and moving the code to Windows OS, the code will break! os.path utils knows how to return correct path considering the OS the code running on. for more info https://docs.python.org/2/library/os.path.html – Mercury Jul 31 '18 at 08:30
  • @MosheRabaev and if you use ".." without the `dirname(realpath(__file__))`, then it will compute the path relative to your current working directory when you run the script, not relative to where the script lives. – TJ Ellis Dec 20 '18 at 19:20
5

Create an empty file __init__.py in subdirectory /lib. And add at the begin of main code

from __future__ import absolute_import 

then

import lib.BoxTime as BT
...
BT.bt_function()

or better

from lib.BoxTime import bt_function
...
bt_function()
Mik
  • 59
  • 1
  • 3
5

Just an addition to these answers.

If you want to import all files from all subdirectories, you can add this to the root of your file.

import sys, os
sys.path.extend([f'./{name}' for name in os.listdir(".") if os.path.isdir(name)])

And then you can simply import files from the subdirectories just as if these files are inside the current directory.

Working example

If I have the following directory with subdirectories in my project...

.
├── a.py
├── b.py
├── c.py
├── subdirectory_a
│   ├── d.py
│   └── e.py
├── subdirectory_b
│   └── f.py
├── subdirectory_c
│   └── g.py
└── subdirectory_d
    └── h.py

I can put the following code inside my a.py file

import sys, os
sys.path.extend([f'./{name}' for name in os.listdir(".") if os.path.isdir(name)])

# And then you can import files just as if these files are inside the current directory

import b
import c
import d
import e
import f
import g
import h

In other words, this code will abstract from which directory the file is coming from.

Victor
  • 671
  • 9
  • 10
-1

/project/tester.py

/project/lib/BoxTime.py

create blank file __init__.py down the line till you reach the file

/project/lib/somefolder/BoxTime.py

#lib -- needs has two items one __init__.py and a directory named somefolder #somefolder has two items boxtime.py and __init__.py

piman314
  • 4,834
  • 18
  • 32
-3

try this:

from lib import BoxTime

Orane
  • 1,909
  • 1
  • 18
  • 29