sibling - python relative import




Importing files from different folder (14)

First import sys

 import sys

Second append the folder path

sys.path.insert(0, '/the/folder/path/name-folder/')

Third Make a blank file called __ init __.py in your subdirectory (this tells Python it is a module)

  • name-file.py
    • name-folder
      • __ init __.py
      • name-module.py

Fourth import the module inside the folder

from name-folder import name-module

I have the following folder structure.

application/app/folder/file.py

and I want to import some functions from file.py in another Python file which resides in

application/app2/some_folder/some_file.py

I've tried

from application.app.folder.file import func_name

and some other various attempts but so far I couldn't manage to import properly. How can I do this?


The answers here are lacking in clarity, this is tested on Python 3.6

With this folder structure:

main.py
|
---- myfolder/myfile.py

Where myfile.py has the content:

def myfunc():
    print('hello')

The import statement in main.py is:

from myfolder.myfile import myfunc
myfunc()

and this will print hello.


Considering application as the root directory for your python project, create an empty __init__.py file in application, app and folder folders. Then in your some_file.py make changes as follows to get the definition of func_name:

import sys
sys.path.insert(0, r'/from/root/directory/application')

from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()

From what I know, add an __init__.py file directly in the folder of the functions you want to import will do the job.


I was faced with the same challenge, especially when importing multiple files, this is how I managed to overcome it.

import os, sys

from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))

from root_folder import file_name

I'm quite special : I use Python with Windows !

I just complete information : for both Windows and Linux, both relative and absolute path work into sys.path (I need relative paths because I use my scripts on the several PCs and under different main directories).

And when using Windows both \ and / can be used as separator for file names and of course you must double \ into Python strings,
some valid examples :

sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')

(note : I think that / is more convenient than \, event if it is less 'Windows-native' because it is Linux-compatible and simpler to write and copy to Windows explorer)


In Python 3.4 and later, you can import from a source file directly (link to documentation).

Here is an example. First, the file to be imported, named foo.py:

def announce():
    print("Imported!")

The code that imports the file above, inspired heavily by the example in the documentation:

import importlib, importlib.util, os.path

def module_from_file(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

foo = module_from_file("foo", "/path/to/foo.py")

if __name__ == "__main__":
    print(foo)
    print(dir(foo))
    foo.announce()

The output:

<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

Note that the variable name, the module name, and the filename need not match. This code still works:

import importlib, importlib.util, os.path

def module_from_file(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

baz = module_from_file("bar", "/path/to/foo.py")

if __name__ == "__main__":
    print(baz)
    print(dir(baz))
    baz.announce()

The output:

<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

Programmatically importing modules was introduced in Python 3.1 and gives you more control over how modules are imported. Refer to the documentation for more information.


In my case I had a class to import. My file looked like this:

# /opt/path/to/code/log_helper.py
class LogHelper:
    # stuff here

In my main file I included the code via:

path.append("/opt/path/to/code/")
from log_helper import LogHelper

So I had just right clicked on my IDE, and added a new folder and was wondering why I wasn't able to import from it. Later I realized I have to right click and create a Python Package, and not a classic file system folder. Or a post-mortem method being adding an __init__.py (which makes python treat the file system folder as a package) as mentioned in other answers. Adding this answer here just in case someone went this route.


This works for me on windows

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file

Using sys.path.append with an absolute path is not ideal when moving the application to other environments. Using a relative path won't always work because the current working directory depends on how the script was invoked.

Since the application folder structure is fixed, we can use os.path to get the full path of the module we wish to import. For example, if this is the structure:

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

And let's say that you want to import the "mango" module. You could do the following in vanilla.py:

import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

Of course, you don't need the mango_dir variable.

To understand how this works look at this interactive session example:

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

And check the os.path documentation.


When modules are in parallel locations, as in the question:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

This shorthand makes one module visible to the other:

import sys
sys.path.append('../')

You can refresh the Python shell by pressing f5, or go to Run-> Run Module. This way you don't have to change the directory to read something from the file. Python will automatically change the directory. But if you want to work with different files from different directory in the Python Shell, then you can change the directory in sys, as Cameron said earlier.


Your problem is that Python is looking in the Python directory for this file and not finding it. You must specify that you are talking about the directory that you are in and not the Python one.

To do this you change this:

from application.app.folder.file import func_name

to this:

from .application.app.folder.file import func_name

By adding the dot you are saying look in this folder for the application folder instead of looking in the Python directory.





python-import