48

I have this structure of files (directory and after arrow files):

model -> py_file.py 
report -> other_py_file.py

main __init__.py:

import model
import report

model directory:

import py_file

report directory:

import other_py_file

now in other_py_file I want to import py_file, but what ever I try I give error that there is no such module.

I tried this: from model import py_file

Then: import py_file

Looks like these two folders don't see each other. What is the way to import file from other directory? Do I need to specify some additional imports in init.py files?

Andrius
  • 19,658
  • 37
  • 143
  • 243
  • 4
    You can't import backwards in a folder structure, your structure is intended to be used from the root and do `import report` which will import `other_py_file`.. Doing `import ../model` will not work. – Torxed Apr 09 '14 at 07:31
  • 1
    @Torxed Found the way using link provided by you. Which was I needed to use import from app folder name like: `from my_app.model import py_file`. I tried something similar like `from addons.my_app.model import py_file`. When that didn't work, I thought I needed to do something else and skipped the part importing just from app directory. – Andrius Apr 09 '14 at 07:36
  • Check my solution below instead.. it fits your model of programming better i think. – Torxed Apr 09 '14 at 07:38
  • @Torxed I think better solution is to just use specific path as in one of the answers provided in your link, because mainly I don't need to import many files in a way I needed now. – Andrius Apr 09 '14 at 07:52
  • My answer uses specific (absolute) paths, and can be combined with `os.walk()` for instance if you want to import stuff dynamicly, or just create a `def superimport(name, path):` and call that for each module you want to import. Just a thought. – Torxed Apr 09 '14 at 07:54
  • the "marked duplicate" _("How to do relative imports in Python?")_ isn't really a duplicate of _this_ question, since that other one assumes relative imports vs just "any" directory (e.g., `/tmp` or `~/temp`). So, see also, http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path – michael Mar 13 '17 at 02:36

2 Answers2

81

You can add to the system-path at runtime:

import sys
sys.path.insert(0, 'path/to/your/py_file')

import py_file

This is by far the easiest way to do it.

anon582847382
  • 19,907
  • 5
  • 54
  • 57
  • 3
    Yea this is an easy way, that can cause issues when importing from a folder where you have the same filename as another library for instance. Altho that would be the case in the OP anyway so i guess it doesn't harm... – Torxed Apr 09 '14 at 07:52
  • 2
    @Torxed I inserted the path at the beginning deliberately so that the custom path is searched first to handle name conflicts, so that wouldn't be a problem. – anon582847382 Apr 09 '14 at 08:00
  • 2
    What about when you have a different path on your PROD application? This may work on your local, but how can you make the file imports work on all machines without having to set a hard file path? – Jeff Gruenbaum Feb 24 '21 at 20:42
25

Python3:

import importlib.machinery

loader = importlib.machinery.SourceFileLoader('report', '/full/path/report/other_py_file.py')
handle = loader.load_module('report')

handle.mainFunction(parameter)

This method can be used to import whichever way you want in a folder structure (backwards, forwards doesn't really matter, i use absolute paths just to be sure).

There's also the more normal way of importing a python module in Python3,

import importlib
module = importlib.load_module('folder.filename')
module.function()

Kudos to Sebastian for spplying a similar answer for Python2:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
Torxed
  • 22,866
  • 14
  • 82
  • 131
  • 3
    Isn't this overcomplicating it? – anon582847382 Apr 09 '14 at 07:52
  • 2
    @AlexThornton Not really, since the user want's to import python-files out of the project scope I personally think it's better to use absolute paths to import things rather than appending to the global import scope. Mine is also more fault tolerant which i preach is a good thing :) – Torxed Apr 09 '14 at 07:55
  • @AlexThornton Well obviously it's not completely idiot proof, but you could theoretically import `/home/time.py` without replacing the bundled `time` library. Assuming the OP doesn't prepend `sys.path` this would ensure you import the correct library no matter what, doesn't matter how you do it, the path you supply will effectively be the module imported. You can also customize namespaces which you can't if doing the traditional `import ...`. More over this will turn into a flame-war over which solution is best, something i'm not going to promote, this is a matter of taste, that's it :) – Torxed Apr 09 '14 at 08:05
  • 1
    @AlexThornton To clarify, your solution is not bad, and it does work. So again, it's a taste thing which style you prefer over the other because the net result will be the same. – Torxed Apr 09 '14 at 08:07
  • do I need to import each file separately? how can I import multiple files from one dir? –  May 08 '18 at 11:17
  • I got it: if I specify `__init__.py`, the whole package will be imported. –  May 08 '18 at 12:46