2448

I have this folder structure:

application
├── app
│   └── folder
│       └── file.py
└── app2
    └── some_folder
        └── some_file.py

How can I import a function from file.py, from within some_file.py? I tried:

from application.app.folder.file import func_name

but it doesn't work.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Ivan
  • 28,999
  • 6
  • 24
  • 21
  • 2
    Related: http://stackoverflow.com/q/43476403/674039 – wim Apr 18 '17 at 15:56
  • 4
    Reading the official documentation helped me a lot! https://docs.python.org/3/reference/import.html#package-relative-imports – Kavin Raju S May 14 '20 at 01:20
  • If you have a dash in the name of the subfolder, it SHOULD BE UNDERSCORE. For example my-package and inside you have my_app folder and tests folder. If my_app is named my-app, you will have import problems – Gonzalo Apr 28 '21 at 15:01
  • Neither `application` nor `app1`, `app2`, `folder`, `some_folder` are packages, and do not contain `__init__.py`, right? If you're going to be doing a lot of this, time to make them a package. – smci Jun 14 '21 at 23:26
  • It depends whether you understand `app` and `app2` as two logically separate projects/packages or not. If they are separate (for example the `app` is a common utility for several apps `app2`, `app3`, ...) then you can [install the `app` from its Github repository](https://stackoverflow.com/questions/4830856/is-it-possible-to-use-pip-to-install-a-package-from-a-private-github-repository) into `app2`'s (virtual) environment as a dependency using `pip` and then use it the same way you use any other third-party package. – Jeyekomon Dec 17 '21 at 13:22
  • How do I deploy the same on aws lambda using aws sam? – user3807691 Jan 22 '22 at 16:42
  • 177
    The fact that this is so hard and there are multiple answers about it, some of which don't work or are hacks, is probably the worst, saddest thing about Python. – JohnAllen Jun 24 '22 at 09:06
  • @JohnAllen it's not actually that hard. There are just a few conceptual issues that are poorly explained. A lot of the answers are duplicates, or re-organizations of various subsets of the same few simple ideas. – Karl Knechtel Aug 28 '22 at 02:29
  • A big source of confusion for me was that certain IDEs will make this problem disappear. In OP's example, running `some_file.py` should cause `ModuleNotFoundError: No module named 'application'`, however if you run the file in PyCharm it will work! This is because PyCharm automatically appends the project root to `sys.path` so the `application` package is visible. My related question [here](https://stackoverflow.com/q/75990606/3620725) gives a more complete example and some solutions. – pyjamas Apr 12 '23 at 21:17
  • Another point of confusion is that when you have your project root in `sys.path` it [runs](https://imgur.com/9nPBT3k) with no errors even if you don't have any `__init__.py` files. This contradicts many highly upvoted comments and answers. – pyjamas Apr 12 '23 at 21:28

40 Answers40

2229

Note: This answer was intended for a very specific question. For most programmers coming here from a search engine, this is not the answer you are looking for. Typically you would structure your files into packages (see other answers) instead of modifying the search path.


By default, you can't. When importing a file, Python only searches the directory that the entry-point script is running from and sys.path which includes locations such as the package installation directory (it's actually a little more complex than this, but this covers most cases).

However, you can add to the Python path at runtime:

    # some_file.py
    import sys
    # caution: path[0] is reserved for script path (or '' in REPL)
    sys.path.insert(1, '/path/to/application/app/folder')

    import file

mirekphd
  • 4,799
  • 3
  • 38
  • 59
Cameron
  • 96,106
  • 25
  • 196
  • 225
  • 550
    `sys.path.append('/path/to/application/app/folder')` is cleaner imo – pseudosudo Sep 01 '11 at 21:48
  • 525
    @pseudosudo: Yep, it is, but inserting it at the beginning has the benefit of guaranteeing that the path is searched before others (even built-in ones) in the case of naming conflicts. – Cameron Sep 02 '11 at 02:47
  • 1
    Now if only Python `lists` had a `prepend` method so that the best choice wouldn't be ugly looking. I understand the reason why `prepend` doesn't exist (because it would have worse run times than `append`), but it seems to be a moot reason. Shouldn't easy to read be valued over quick to run? – ArtOfWarfare Oct 31 '13 at 18:54
  • @ArtOfWarfare deques solve the runtime issue, and they have an appendleft method. If you need a list, use a list, if you need a deque, use a deque. – kreativitea Nov 03 '13 at 18:34
  • 10
    @kreativitea - `sys.path` returns a `list`, not a `deque`, and it'd be silly to convert the `list` to a `deque` and back. – ArtOfWarfare Nov 03 '13 at 20:35
  • 57
    Is it considered as a pythonic way to manage .py files in folders? I'm wondering... why it's not supported by default? it doesn't make sense to maintain all .py files in a single directory.. – Ofir Sep 20 '15 at 18:32
  • 75
    @Ofir: No, this isn't a nice clean pythonic solution. In general, you should be using packages (which are based on directory trees). This answer was specific to the question asked, and for some reason continues to accrue a large number upvotes. – Cameron Sep 21 '15 at 02:38
  • 2
    @Cameron What exactly is "the directory that the entry-point script is running from" mean? Thanks! – AdjunctProfessorFalcon Aug 20 '16 at 23:11
  • 2
    @Malvin9000 That means that if the file you are working on is not the main file for the program. For example say you are working on a module named `foo` and you want it imports a package named `bar`. Now if you write another script, `spam` that imports `foo` then `spam` is the entry-point script, and that when `foo` calls `import bar` python will search in `foo`'s directory and then the directory containing `spam`. – calder-ty Aug 21 '16 at 19:58
  • 2
    I already have the path in sys.path. When I do `print(sys.path)` it shows me the path is there but when I try and import it still gives me the **ImportError**. Why could this be happening? – Haseeb Jun 10 '17 at 14:55
  • 2
    @Cameron: Could you then provide the clean pythonic way to do this, or a link to the solution? – rain_ Jun 20 '17 at 15:11
  • 1
    @rain_: Use [Python packages](https://docs.python.org/2/tutorial/modules.html#packages) as suggested by joey's answer. – Cameron Jun 20 '17 at 16:18
  • 2
    @Cameron. It does not work for me. Im using a project folder. with some subfolders on it. One of those subfolders containts an __init__.py and files.py which has functions on them. From any file in a subfolder I use: from functions_folder.functions import *, and it just doesnt work. – rain_ Jun 21 '17 at 09:43
  • @GabrielStaples yes, it does work on relative paths. – Andreas Forslöw Sep 24 '19 at 19:41
  • Another thing worth pointing out about this approach, which makes it non-pythonic, is that you cannot have the same name for any of your `sys.path` modules as one of your local modules. I.e. you cannot import `sys/path/module.py` to your `current/package/main.py` if `current/package/main.py` imports `current/package/module.py`. In other words, all the imported modules has to have unique names. – Andreas Forslöw Sep 24 '19 at 19:48
  • It's important to note that even if you use something like `os.path.abspath` aliases like `~` for your home directory are not replaced. – McLawrence Apr 23 '20 at 10:19
  • 2
    Interesting. It only takes a path as a string. It does not accept a path object. – Steve Scott Jun 12 '20 at 17:52
  • 1
    Doesn't work for me. I have a file `foo` which I import, which in turn imports `conftest`, which located at a `../conftest.py` file. So I do `sys.path.append(tests_dir)`, where `tests_dir` I tried to be both `../` and an absolute path. However upon executing `import foo` I still get "No module test named 'conftest'`. – Hi-Angel Jul 27 '20 at 09:43
  • @Hi-Angel , does this solve your problem?: https://stackoverflow.com/questions/62886769/is-it-possible-to-import-a-python-file-from-outside-the-directory-the-main-file – theX Aug 05 '20 at 01:19
  • @theX thanks, I should try it. For now I worked around this be placing the script in a different directory. – Hi-Angel Aug 05 '20 at 06:19
  • Hi guys, I have the same problem but the solution doesnt work. the path in the brackets is underlined and can't be find. What can I do? Its the correct path – Shalomi90 Sep 07 '20 at 15:13
  • 1
    @Shalomi11 On Windows, I recommend `sys.path.insert(1, os.path.abspath('/path/to/application/app/folder'))`, since with the notation above, the slashs are not how they should be in Windows. (You can check this if you put a breakpoint after this line and then in the debug mode, check "sys.path") – Isi Sep 25 '20 at 08:34
  • 1
    @Cameron Can you link to the pythonic solution you described, involving packages and directory trees? – young_souvlaki Mar 26 '21 at 17:59
  • would it be possible to add all those "custom" packages in a common python file or do you need to add this line in all the .py files that need to import those custom modules? – HAL9000 Aug 21 '21 at 07:36
  • @Cameron thanks for your helpful answer. It has at least one more special case which I found useful. And that case is when I want to include my python file to the Spyder and Jupyter platforms from my own library. Same code should work in both platforms and when I copy and it does. – Sermet Pekin Dec 03 '21 at 14:25
  • It's also worth mentioning that if you use PyCharm or Spyder then by default you *can* just use absolute imports without any errors because the IDE automatically adds your project directory to `sys.path`, which is the same thing this answer does. I think that's why there are wrong answers like joey's saying it should just work with so many upvotes. See also [Automatically add project to sys.path in VS Code](https://stackoverflow.com/q/75990606) – pyjamas Apr 12 '23 at 22:05
1304

There is nothing wrong with:

from application.app.folder.file import func_name

Just make sure folder also contains an __init__.py. This allows it to be included as a package. I am not sure why the other answers talk about PYTHONPATH.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
joey
  • 13,367
  • 1
  • 14
  • 8
  • 83
    Because this doesn't cover the cases where modifying `PYTHONPATH` is necessary. Say you have two folders on the same level: `A` and `B`. `A` has an `__init.py__`. Try importing something from `B` within `A`. – msvalkon Mar 06 '14 at 13:45
  • that's what i was looking for, ie works with standard local lib directory – zlr Apr 15 '14 at 11:48
  • 8
    this is a great answer - I was missing the __init__.py to initialize the package. Also encourages best practice so that there's less risk of namespace collision. Thanks! – sofly Nov 04 '14 at 20:20
  • 82
    What's inside the `init.py` or `__init__.py` file? – XY L May 09 '15 at 02:16
  • 88
    @Xinyang It can be an empty file. Its very existence tells Python to treat the directory as a package. – jay May 11 '15 at 23:24
  • 2
    `__init__.py` syntax is described in more detail in https://docs.python.org/3/tutorial/modules.html#packages and is useful if the package resides in a system or PYTHONPATH (sub-)dir or inside a dir of the calling application itself. – Ax3l Dec 06 '15 at 13:34
  • 31
    This is not currently the highest voted answer, but it IS the most correct answer (for most cases). Simply create a package. It's not hard. The other answers are needed because sometimes you might be restricted from certain system changes (creating or modifying a file, etc) like during testing. – Scott Prive Mar 03 '16 at 18:59
  • 2
    The empty __init__.py is vital in the container directory, thanks. – Sunding Wei Sep 12 '16 at 08:42
  • 18
    Of course this answer assumes that `application` and `app` are packages already (i.e. you already have `__init__.py` in both of them). As the result of adding `__init__.py` also to `folder`, `application.app.folder` becomes a (sub) *package*, from which you can access the *module* `application.app.folder.file`, whose symbol `func_name` can now be imported – Yibo Yang Apr 29 '17 at 07:12
  • 84
    Whatever I try, this won't work. I want to import from a "sibling" directory, so one up one down. All have __ init __.py's, including parent. Is this python 3 -specific? – dasWesen Jun 18 '17 at 12:54
  • 1
    @dasWesen, don't think it should differ much, but if this doesn't help you, ask a new one – borgr Oct 24 '17 at 11:57
  • 2
    @borgr I think I circumvented it back then... Sorry, I don't remember what code that problem was in, this was too long ago (and it's not relevant for me right now). But there seems to be a common issue, so if anyone else has the problem right now, yes, please go ahead and open a new question. – dasWesen Oct 30 '17 at 11:10
  • 1
    @msvalkon If changing the path to directory B won't break your program, you can use symbolic links along with this answer to solve that problem. Let's say you're in directory A and want to import something in directory B. Add `__init__.py` to directory B. Make a symbolic link of directory B; put it in directory A. In directory A, `import B.yourModule`. – Brōtsyorfuzthrāx Feb 22 '18 at 09:50
  • 2
    Is there a solution to this problem now? I can't find a way to circumvent the problem and I find it very confusing to have all files for one single program in one folder – SnitchingAuggie Jun 11 '18 at 21:55
  • This is the easiest solution – SMDC Jun 20 '18 at 06:31
  • 21
    running this script in command line with py3.7 on Windows gives me `No module named application.app.folder.file`. I have all the __init__.py in place including the one for the parent folder – kakyo Jun 07 '19 at 10:37
  • If my folder name is a_b_c and which contains app.py so how we can access it? @joey – Ashu Jul 29 '19 at 07:23
  • 2
    Is the `__init__.py` still required, given implicit package namespace? – Minh Nghĩa Nov 21 '19 at 15:41
  • 3
    i have folder `a/test.py` and the file `b.py` as the same level of a folder. even by adding a `__init__.py` file to the root folder (as side of `a` folder with `b.py`) i cant import a function from `b.py` file inside `test.py`... – amdev Dec 17 '19 at 06:06
  • How would `application.app.folder.file` be changed in case there was a space in the name of the folder? Doesn't seem to be any clear answer to that. – Yeahprettymuch Jul 01 '20 at 10:56
  • 5
    This sounds like a joke. Many guys writing a lot of things about what is right and don't and finally someone says that is not "nothing wrong with"... – mold Jul 06 '20 at 18:44
  • 3
    Wish Python 4 does something sensible about this so called Package system. No ,matter ow many `__init__.py` you put in place, python always fails to find modules. – pouya Dec 03 '20 at 17:55
  • 2
    Working and not working ... works when I try `from A.file import funcA` at level `Z` (folder that has A and B as sub-folder) at the IPython console. However, running `funcB` inside `B` folder that has `from A.file import funcA` fails and throws the error (ModuleNotFoundError: No module named 'FashionColor'). Note that running `funcB` will change the working directory to `B`. All folders have __init__.py. – Mohd Jan 19 '21 at 17:24
  • 7
    I am using python3, and it does not work for me – Lei_Bai Apr 14 '21 at 17:41
  • 3
    In order to get this working for me, I had to add the lines `import sys` and `sys.path.insert(0, '')` before importing the module – martin36 Aug 05 '21 at 09:35
  • 1
    ModuleNotFoundError: No module named 'application' :( – ashrasmun Aug 26 '21 at 08:49
  • If you are using a PEP8 formatter, you will run into problems here since module imports are automatically sorted to the top of the file for imports. You can use #noqa to ignore these lines... but wowza that's ugly – Andrew K Oct 20 '21 at 19:42
  • 2
    This doesn't work. Simple as that. It SHOULD work, but it doesn't. – JohnAllen Jun 24 '22 at 09:07
  • 1
    it doesn't work – KansaiRobot Oct 24 '22 at 08:29
  • 1
    This doesnt work, its so weird – Pit Digger Nov 11 '22 at 22:54
  • Does note work for files in sibling directories. – Bebotron Nov 17 '22 at 22:41
  • this is not worked for me. but `PYTHONPATH` worked – Alirezaarabi Dec 19 '22 at 19:35
  • I don't think this works with Python 3.8. I had issues using this approach. – benso8 Jan 20 '23 at 20:02
  • 2
    Even with `__init__.py` in every folder, absolute imports of adjacent packages doesn't work unless the root directory is in PYTHONPATH. I'm not sure how there are 1200 upvotes on an answer that just [doesn't work](https://i.imgur.com/4J5BKVL.png)... I'm assuming anyone not getting `ModuleNotFoundError` is running their code through an IDE like PyCharm that automatically adds the project directory to `sys.path`. You can read more [here](https://stackoverflow.com/q/75990606/3620725) and [here](https://stackoverflow.com/q/14132789/3620725) – pyjamas Apr 12 '23 at 20:59
238

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('../')
slizb
  • 5,742
  • 4
  • 25
  • 22
  • 43
    As a caveat: This works so long as the importing script is run from its containing directory. Otherwise the parent directory of whatever other directory the script is run from will be appended to the path and the import will fail. – Carl Smith May 03 '17 at 03:02
  • 30
    To avoid that, we can get the parent directory of file `sys.path.append(os.path.dirname(os.path.abspath(__file__)))` – Rahul Sep 17 '18 at 10:09
  • 2
    That didn't work for me - I had to add an additional dirname in there to climb back up to the parent, so that running ```cli/foo.py``` from the command line was able to ```import cli.bar``` – RCross Jul 26 '19 at 11:23
  • 3
    @Rahul, your solution doesn't work for interactive shells – towi_parallelism Nov 27 '19 at 18:19
  • 6
    If you run it from your root folder (ie. application folder), you are probably fine with `sys.path.append('.')` then importing the module by using `from app2.some_folder.some_file import your_function`. Alternatively what works for me is running `python3 -m app2.another_folder.another_file` from root folder. – addicted Dec 16 '19 at 13:23
  • 1
    I find this to be the simplest way. just append the relative file path to the file containing the module you need. in my case: import sys sys.append('../data_structure/') . the module is in a file inside of the data_structure/ folder – Amir Dec 21 '19 at 18:47
  • So every directory I want to import from needs three total lines of code to import a single file from each directory? Or is `path.append` by default recursive? – JohnAllen Jun 24 '22 at 09:08
  • Rather than appending to system path, inserting custom package folder at 1st position in the path would be more robust (to name collisions, that are rather likely, e.g. when debugging a temporary copy of an official package copied from a write-protected location). – mirekphd Aug 14 '22 at 08:53
120

First import sys in name-file.py

 import sys

Second append the folder path in name-file.py

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

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

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

Fourth import the module inside the folder in name-file.py

from name-package import name-module
Alex Montoya
  • 4,697
  • 1
  • 30
  • 31
  • 11
    With name-folder being right below name-file.py, this should work even without the `sys.path.insert`-command. As such, the answer leaves the question, if this solution works even when name-folder is located in an arbitrary location. – Bastian Feb 01 '19 at 09:19
  • are you saying that I have to hardcode the path to the script? This means that the solution is not portable. Also the question is how to access from one subfolder to the other. Why not following the name convention and file structure of the original question? – Giacomo Mar 13 '21 at 18:40
  • @Giacomo You don't have to hardcode anything. Just pass it as a parameter to the script. – Jeyekomon Nov 15 '21 at 16:03
  • Caution: insert at position 1, since position 0 is the script path (or '' in REPL). – mirekphd Aug 14 '22 at 08:55
  • Thanks for this answer @Alex Montoya! Upvoted! – Deepak Tatyaji Ahire Jul 13 '23 at 10:34
76

I think an ad hoc way would be to use the environment variable PYTHONPATH as described in the documentation: Python2, Python3

# Linux and OS X
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ax3l
  • 1,529
  • 12
  • 20
  • Wait, would I replace myScripts with the filename? – Vladimir Putin Jun 29 '14 at 22:45
  • 7
    no, with the path of the directory to your .py file – Ax3l Jul 05 '14 at 13:57
  • 4
    Unfortunately, if you are using Anaconda, this won't work, since under the hood PYTHONPATH is not really used internally ! – information_interchange Apr 13 '20 at 01:28
  • 1
    For (recent) changes in anaconda, see this SO for workflows and comments for work-arounds: https://stackoverflow.com/questions/17386880/does-anaconda-create-a-separate-pythonpath-variable-for-each-new-environment Generally speaking, build and install small packages instead of hacking the import dirs. – Ax3l Apr 14 '20 at 08:53
68

Try Python's relative imports:

from ...app.folder.file import func_name

Every leading dot is another higher level in the hierarchy beginning with the current directory.


Problems? If this isn't working for you then you probably are getting bit by the many gotcha's relative imports has. Read answers and comments for more details: How to fix "Attempted relative import in non-package" even with __init__.py

Hint: have __init__.py at every directory level. You might need python -m application.app2.some_folder.some_file (leaving off .py) which you run from the top level directory or have that top level directory in your PYTHONPATH. Phew!

Zectbumo
  • 4,128
  • 1
  • 31
  • 26
64

The issue is that Python is looking in the wrong directory for the file. To solve this, try using relative import. Change

from application.app.folder.file import func_name

to:

from .application.app.folder.file import func_name

Adding the dot instructs Python to look for the application folder within the current folder, instead of in the Python install folder.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
CianB
  • 927
  • 7
  • 12
50

Given a folder structure like

├── main.py
└── myfolder
    └── myfile.py

Where myfile.py contains

def myfunc():
    print('hello')

To call myfunc from main.py, use:

from myfolder.myfile import myfunc
myfunc()
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
danday74
  • 52,471
  • 49
  • 232
  • 283
49

In Python 3.4 and later, you can import from a source file directly (link to documentation). This is not the simplest solution, but I'm including this answer for completeness.

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.util

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.util

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.

wecsam
  • 2,651
  • 4
  • 25
  • 46
41

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.

Also worth noting that dealing with multiple folders is made easier when using packages, as one can use dotted module names.

Nagev
  • 10,835
  • 4
  • 58
  • 69
40

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

Berci
  • 544
  • 1
  • 7
  • 10
Vaibhav Singh
  • 427
  • 4
  • 2
32

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
Erick Mwazonga
  • 1,020
  • 12
  • 25
  • 5
    You answer would be more helpful if you could explain what it does differently from an ordinary import? – not2qubit Apr 23 '19 at 19:25
  • 1
    I had /path/dir1/__init__.py and /path/dir1/mod.py. For /path/some.py from dir1.mod import func worked. When in /path/dir2/some.py it only worked after I copied and pasted the above answer at the top of the file. Didn't want to edit my path since not every python project I have is in /path/. – jwal May 02 '19 at 11:52
  • My test files were moved to another directory when running it using `bazel` after adding this import, the test files were able to reference the dependencies. – Vishrant Oct 19 '21 at 19:50
30

This worked for me in Python 3 on Linux:

import sys
sys.path.append(pathToFolderContainingScripts)
from scriptName import functionName #scriptName without .py extension
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dsg38
  • 544
  • 5
  • 10
29

Considering application as the root directory for your Python project, create an empty __init__.py file in the 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()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ChandanK
  • 607
  • 7
  • 10
22

One way is to create a package and use absolute import to access other modules from the package. Start the program from a script at the root of the package. This structure allows using and accessing sub-packages, parent package, and sibling packages and modules.

As an example, try creating the following folder structure:

package/
├── __init__.py
├── main_module.py
├── module_0.py
├── subpackage_1/
|   ├── __init__.py
|   ├── module_1.py
|   └── sub_subpackage_3/
|       ├── __init__.py
|       └── module_3.py
└── subpackage_2/
    ├── __init__.py
    └── module_2.py

Contents of main_module.py:

import subpackage_1.module_1

Contents of module_0.py:

print('module_0 at parent directory, is imported')

Contents of module_1.py:

print('importing other modules from module_1...')
import module_0
import subpackage_2.module_2
import subpackage_1.sub_subpackage_3.module_3

Contents of module_2.py:

print('module_2 at same level directory, is imported')

Contents of module_3.py:

print('module_3 at sub directory, is imported')

Leave all __init__.py files empty.

Now run main_module.py; the output will be

importing other modules from module_1...
module_0 at parent directory, is imported
module_2 at same level directory, is imported
module_3 at sub directory, is imported
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Mohsen Haddadi
  • 1,296
  • 2
  • 16
  • 20
21
├───root
│   ├───dir_a
│   │   ├───file_a.py
│   │   └───file_xx.py
│   ├───dir_b
│   │   ├───file_b.py
│   │   └───file_yy.py
│   ├───dir_c
│   └───dir_n

You can add the parent directory to PYTHONPATH, in order to achieve that, you can use OS depending path in the "module search path" which is listed in sys.path. So you can easily add the parent directory like following:

# file_b.py

import sys
sys.path.insert(0, '..')

from dir_a.file_a import func_name
Milovan Tomašević
  • 6,823
  • 1
  • 50
  • 42
  • 1
    The magic here is to use '.' instead of '/' to indicate the path relative to current path. – mike Oct 06 '22 at 14:01
15

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Emeeus
  • 5,072
  • 2
  • 25
  • 37
13

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:

import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper
Walter
  • 184
  • 2
  • 13
schmudu
  • 2,111
  • 1
  • 21
  • 30
12

I bumped into the same question several times, so I would like to share my solution.

Python Version: 3.X

The following solution is for someone who develops your application in Python version 3.X because Python 2 is not supported since Jan/1/2020.

Project Structure

In python 3, you don't need __init__.py in your project subdirectory due to the Implicit Namespace Packages. See Is init.py not required for packages in Python 3.3+

Project 
├── main.py
├── .gitignore
|
├── a
|   └── file_a.py
|
└── b
    └── file_b.py

Problem Statement

In file_b.py, I would like to import a class A in file_a.py under the folder a.

Solutions

#1 A quick but dirty way

Without installing the package like you are currently developing a new project

Using the try catch to check if the errors. Code example:

import sys
try:
    # The insertion index should be 1 because index 0 is this file
    sys.path.insert(1, '/absolute/path/to/folder/a')  # the type of path is string
    # because the system path already have the absolute path to folder a
    # so it can recognize file_a.py while searching 
    from file_a import A
except (ModuleNotFoundError, ImportError) as e:
    print("{} fileure".format(type(e)))
else:
    print("Import succeeded")

#2 Install your package

Once you installed your application (in this post, the tutorial of installation is not included)

You can simply

try:
    from __future__ import absolute_import
    # now it can reach class A of file_a.py in folder a 
    # by relative import
    from ..a.file_a import A  
except (ModuleNotFoundError, ImportError) as e:
    print("{} fileure".format(type(e)))
else:
    print("Import succeeded")

Happy coding!

WY Hsu
  • 1,837
  • 2
  • 22
  • 33
  • for more info about [absolute imports](https://stackoverflow.com/questions/42853617/python-fails-importing-package) – WY Hsu Jan 05 '20 at 09:36
  • 1
    your first proposed solution worked for me using sys.path.insert(1, '../a/') which I think is better than writing the full path. – Giacomo Mar 13 '21 at 18:49
  • In case someone has a local package that you would like to import instead of the system package (THAT HAS THE SAME NAME) please use sys.path.insert(1,'folder-to-grab-package-from') instead of sys.append('folder-to-grab-package-from') – MedoAlmasry Mar 15 '21 at 11:02
  • You say "You can simply" but unfortunately seven lines of code to import a single file is not simple at all! – JohnAllen Jun 24 '22 at 09:14
11

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

I just complete information: for both Windows and Linux, both relative and absolute paths 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 a separator for file names and of course you must double \ into Python strings. Here are 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 \, even if it is less 'Windows-native', because it is Linux-compatible and simpler to write and copy to Windows Explorer)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
herve-guerin
  • 2,827
  • 20
  • 25
8

Instead of just doing an import ..., do this :

from <MySubFolder> import <MyFile>

MyFile is inside the MySubFolder.

Karthikeyan VK
  • 5,310
  • 3
  • 37
  • 50
8

The following worked for me:

OS: Windows 10

Python: v3.10.0

Note: Since I am Python v3.10.0, I am not using __init__.py files, which did not work for me anyway.

application
├── app
│   └── folder
│       └── file.py
└── app2
    └── some_folder
        └── some_file.py

WY Hsu's first solution worked for me. I have reposted it with an absolute file reference for clarity:

import sys
sys.path.insert(1, 'C:\\Users\\<Your Username>\\application')
import app2.some_folder.some_file

some_file.hello_world()

Alternative Solution: However, this also worked for me:

import sys
sys.path.append( '.' )
import app2.some_folder.some_file

some_file.hello_world()

Although, I do not understand why it works. I thought the dot is a reference to the current directory. However, when printing out the paths to the current folder, the current directory is already listed at the top:

for path in sys.path:
    print(path)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
yerty
  • 323
  • 7
  • 13
  • 1
    For me I had to get up one more branch by doing ```sys.path.append('..')``` and it worked ! But still display the path of the CWD – Tirbo06 Mar 20 '22 at 16:17
7

If the purpose of loading a module from a specific path is to assist you during the development of a custom module, you can create a symbolic link in the same folder of the test script that points to the root of the custom module. This module reference will take precedence over any other modules installed of the same name for any script run in that folder.

I tested this on Linux but it should work in any modern OS that supports symbolic links.

One advantage to this approach is that you can you can point to a module that's sitting in your own local software version control branch working copy which can greatly simplify the development cycle time and reduce failure modes of managing different versions of the module.

Timothy C. Quinn
  • 3,739
  • 1
  • 35
  • 47
  • What is *"SVC"*? Do you mean *"[DVC](https://en.wikipedia.org/wiki/Distributed_version_control)"*? Or *"[DVCS](https://en.wikipedia.org/wiki/Distributed_version_control)"*? Or even *"[CVS](https://en.wikipedia.org/wiki/Concurrent_Versions_System)"*, *"[VSS](https://en.wikipedia.org/wiki/Microsoft_Visual_SourceSafe)"*, or *"[SVN](https://en.wikipedia.org/wiki/Apache_Subversion)"*? Or something else? *Source version control*? – Peter Mortensen Mar 28 '23 at 14:11
  • SVC = Software Version Control. Just realized it's not a commonly used acronym but its is the umbrella over all of all version control systems. I'll edit my comment to be more clear. – Timothy C. Quinn Mar 28 '23 at 18:01
  • Great read: https://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1393&context=cstech – Timothy C. Quinn Mar 28 '23 at 18:03
6

I was working on project a that I wanted users to install via pip install a with the following file list:

.
├── setup.py
├── MANIFEST.in
└── a
    ├── __init__.py
    ├── a.py
    └── b
        ├── __init__.py
        └── b.py

setup.py

from setuptools import setup

setup (
  name='a',
  version='0.0.1',
  packages=['a'],
  package_data={
    'a': ['b/*'],
  },
)

MANIFEST.in

recursive-include b *.*

a/init.py

from __future__ import absolute_import

from a.a import cats
import a.b

a/a.py

cats = 0

a/b/init.py

from __future__ import absolute_import

from a.b.b import dogs

a/b/b.py

dogs = 1

I installed the module by running the following from the directory with MANIFEST.in:

python setup.py install

Then, from a totally different location on my filesystem /moustache/armwrestle I was able to run:

import a
dir(a)

Which confirmed that a.cats indeed equalled 0 and a.b.dogs indeed equalled 1, as intended.

duhaime
  • 25,611
  • 17
  • 169
  • 224
6

This worked for me.

Python adds the folder containing the script you launch to the PYTHONPATH, so if you run

python application/app2/some_folder/some_file.py

Only the folder application/app2/some_folder is added to the path (not the base directory that you're executing the command in). Instead, run your file as a module and add a __init__.py in your some_folder directory.

python -m application.app2.some_folder.some_file

This will add the base directory to the path to executable python, and then classes will be accessible via a non-relative import.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Md Shafiul Islam
  • 1,579
  • 1
  • 13
  • 19
5

The code below imports the Python script given by its path, no matter where it is located, in a Python version-safe way:

def import_module_by_path(path):
    name = os.path.splitext(os.path.basename(path))[0]
    if sys.version_info[0] == 2:
        # Python 2
        import imp
        return imp.load_source(name, path)
    elif sys.version_info[:2] <= (3, 4):
        # Python 3, version <= 3.4
        from importlib.machinery import SourceFileLoader
        return SourceFileLoader(name, path).load_module()
    else:
        # Python 3, after 3.4
        import importlib.util
        spec = importlib.util.spec_from_file_location(name, path)
        mod = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(mod)
        return mod

I found this in the codebase of psutils, at line 1042 in psutils.test.__init__.py (most recent commit as of 09.10.2020).

Usage example:

script = "/home/username/Documents/some_script.py"
some_module = import_module_by_path(script)
print(some_module.foo())

Important caveat: The module will be treated as top-level; any relative imports from parent packages in it will fail.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Neinstein
  • 958
  • 2
  • 11
  • 31
  • Any idea why the two different Python3 methods? I tried both on Python 3.6, and they both worked, and returned identical results – Jon May 30 '21 at 22:50
  • Also identical results on python 3.8.9. Starting with 3.8.10 and later, the `spec_from_file_location` starts saving the root path of the file (if a relative path given) in the __loader__ object, but otherwise the data returned is identical. Also tested with python 3.10 -- exact same behavior as 3.8.10. Both methods work just fine. – Jon May 30 '21 at 23:25
  • @Jon Unfortunately I can't comment on these, I'm not familiar with the nuances of importlib. This is found property, and I didn't want to change anything - figured they had a reason for it. Maybe there's some nuance that is different, or that breaks for older/newer versions. – Neinstein May 31 '21 at 07:03
5

This problem may be due to PyCharm

I had the same problem while using PyCharm. I had this project structure

skylake\
   backend\
      apps\
          example.py
      configuration\
          settings.py
   frontend\
      ...some_stuff

and code from configuration import settings in example.py raised an import error.

The problem was that when I opened PyCharm, it considered that skylake is the root path and ran this code.

sys.path.extend(['D:\\projects\\skylake', 'D:/projects/skylake'])

To fix this I just marked backend directory as the source root.

Enter image description here

And it's fixed my problem.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adilet Usonov
  • 139
  • 1
  • 6
5

My solution for people who have all the necessary __init__.py in the package, but import still doesn't work.

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

import application.app.folder.file as file
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sergiusz
  • 92
  • 1
  • 3
  • worked for me... but this should not be like this, python sometimes is complicated to understand... – Jota Mar 21 '23 at 00:50
4

You can use pip's pip install -e . command. You must create a file called setup.py in the root of the project's directory which contains the following:

from setuptools import find_packages, setup

setup(
    name='src',
    packages=find_packages(),
    version='0.1.0',
    description='my_project',
    author='author',
    license='MIT',
)

Afterwards, enter pip install -e . while in your project's root directory. This will enable all directories to be called with their name as a module. For example, if your root directory contains the subdirectories module1 and module2, each with scripts inside them, you will be able to access them from any subdirectories with the following command, for module1:

import module1.script1 as script1

KSHMR
  • 741
  • 1
  • 9
  • 24
3

You can use importlib to import modules where you want to import a module from a folder using a string like so:

import importlib

scriptName = 'Snake'

script = importlib.import_module('Scripts\\.%s' % scriptName)

This example has a main.py which is the above code then a folder called Scripts and then you can call whatever you need from this folder by changing the scriptName variable. You can then use script to reference to this module. such as if I have a function called Hello() in the Snake module you can run this function by doing so:

script.Hello()

I have tested this in Python 3.6

Dextron
  • 598
  • 7
  • 24
3

I usually create a symlink to the module I want to import. The symlink makes sure Python interpreter can locate the module inside the current directory (the script you are importing the other module into); later on when your work is over, you can remove the symlink. Also, you should ignore symlinks in .gitignore, so that, you wouldn't accidentally commit symlinked modules to your repo. This approach lets you even successfully work with modules that are located parallel to the script you are executing.

ln -s ~/path/to/original/module/my_module ~/symlink/inside/the/destination/directory/my_module
picmate 涅
  • 3,951
  • 5
  • 43
  • 52
3

If you have multiple folders and sub folders, you can always import any class or module from the main directory.

For example: Tree structure of the project

Project 
├── main.py
├── .gitignore
|
├── src
     ├────model
     |    └── user_model.py
     |────controller
          └── user_controller.py

Now, if you want to import "UserModel" class from user_model.py in main.py file, you can do that using:

from src.model.user_model.py import UserModel

Also, you can import same class in user_controller.py file using same line:

from src.model.user_model.py import UserModel

Overall, you can give reference of main project directory to import classes and files in any python file inside Project directory.

kepy97
  • 988
  • 10
  • 12
  • do we need `__init__.py` under src to make this happen? – Richie F. Dec 17 '20 at 20:29
  • 3
    This is not an answer to the original question which was NOT about how to import from main.py, but rather (following your example) from user_model.py to user_controller.py. – Giacomo Mar 13 '21 at 18:38
2

You can refresh the Python shell by pressing F5, or go to RunRun 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
IOstream
  • 113
  • 1
  • 6
2

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.

mithunpaul
  • 3,268
  • 22
  • 19
2

I've had these problems a number of times. I've come to this same page a lot. In my last problem I had to run the server from a fixed directory, but whenever debugging I wanted to run from different sub-directories.

import sys
sys.insert(1, /path) 

did NOT work for me because at different modules I had to read different *.csv files which were all in the same directory.

In the end, what worked for me was not pythonic, I guess, but:

I used a if __main__ on top of the module I wanted to debug, that is run from a different than usual path.

So:

# On top of the module, instead of on the bottom
import os
if __name__ == '__main__':
    os.chdir('/path/for/the/regularly/run/directory')
B Furtado
  • 1,488
  • 3
  • 20
  • 34
2

In case you only want to run the script instead of actually importing it, the exec command will do the work

exec(open('/full/or/relative/path').read())
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Daniel N.
  • 174
  • 1
  • 10
1

2023 Python 3.10+ solution

Out of all the answers here, only martin36's solution hidden in the comments worked for me to enable relative imports.

import sys
sys.path.append('')

(But using append instead of insert)

from application.app.folder.file import func_name
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nermin
  • 749
  • 7
  • 17
  • 1
    I can guarantee you that nothing fundamentally has changed in Python in a very long time that would be relevant to this answer. I can also guarantee you that using 3.10 is not relevant to your problem, in particular. I can almost guarantee you that many other answers would have solved your problem. I can almost guarantee you that changing `sys.path` is not necessary for your situation - many of the largest and most important Python libraries, running hundreds of thousands of lines of code, do not use it. Also, what you show here is **not a relative import**. – Karl Knechtel Mar 24 '23 at 05:49
  • Can you explain your answer, please? E.g, why and how does appending an empty string work? Please respond by [editing (changing) your answer](https://XXXX), not here in comments (**** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ***without*** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Mar 28 '23 at 13:04
  • Does it *only* work in Python 3.10 (and later)? Or was it only tested with Python 3.10? `sys.path.append('')` itself executes without error in Python 3.6.9. – Peter Mortensen Mar 28 '23 at 13:11
  • OK, *[Why is the first element in Python's sys.path an empty string?](https://stackoverflow.com/questions/49559003/why-is-the-first-element-in-pythons-sys-path-an-empty-string)* – Peter Mortensen Mar 28 '23 at 13:18
  • If the first element is an empty string, what difference does it make to append an empty string at the end? For instance, is there a Python version dependence? Did they remove the empty string at the beginning in later versions of Python? – Peter Mortensen Mar 28 '23 at 13:20
  • After the append operation on Python 3.6.9, example content of sys.path is: `['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/home/mortensen/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages', '']` – Peter Mortensen Mar 28 '23 at 13:24
  • OK, only in the REPL (or if read from [standard input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin))). – Peter Mortensen Mar 28 '23 at 13:37
  • *[The initialization of the sys.path module search path](https://docs.python.org/3/library/sys_path_init.html)* – Peter Mortensen Mar 28 '23 at 13:45
  • *insert* is also used in [this answer](https://stackoverflow.com/questions/72852/how-can-i-do-relative-imports-in-python) (though not with the same parameter). – Peter Mortensen Mar 28 '23 at 14:38
0

Just in case anyone still needs a solution and hasn't found one in the answers above. This worked for me:

I have this folder structure:

a
└── b
    ├── c1
    |   └── d
    |       └── a_script.py
    └── c2
        └── a_lib.py

And I needed the a_lib.py to be included in the a_script.py. This is how I resolved the error that c2 is not recognized:

import sys
from pathlib import Path
path_scripts = Path(__file__).resolve().parents[2]
sys.path.append(str(path_scripts))
from c2 import a_lib
winsett
  • 71
  • 7
0

There are many awesome answers, but I think it is import to note the PATHONPATH. (Below is excerpted from various online resource. Credit to Internet!)

If you have a function in a Python file in another directory, you can still import it by modifying the Python import path or using a relative import.

Here's how you can do it:

Let's assume you have the following directory structure:

my_project/
│
├── main.py
│
└── my_module/
    ├── __init__.py
    └── my_functions.py

Your my_functions.py defined a function named my_function and you want to use it in main.py.

Here is how you can do it:

from my_module.my_functions import my_function

my_function()  # Outputs: Hello, World!

This assumes that my_project is in your Python path. If you're running main.py from the my_project directory, then Python will add my_project to the Python path automatically and it should be able to find my_module.

If my_project is not in your Python path, you must add it manually at the start of main.py:

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

from my_module.my_functions import my_function

my_function()  # Outputs: Hello, World!

Replace '/path/to/my_project' with the actual path to my_project.

The __init__.py file in my_module is necessary for Python to recognize my_module as a package that can be imported. If my_module doesn't contain __init__.py, simply create an empty file with that name.

Above answers this question post:

Importing files from different folder

For additional reference, if one needs to import functions defined in different files in the same module, here is the example on how to import functions from one file to another file ( under the same module).

Suppose you have the following directory structure:

src/
    __init__.py
    file1.py
    file2.py

Let's say file1.py contains a function function1(), and you want to use this function in file2.py.

In file2.py, you can import the function from file1.py using the following line:

from .file1 import function1

You can then call function1() in file2.py as if it was defined in the same file.

The . before file1 in the import statement is a relative import, which means "import from the same package". In this case, it's saying "import from the same directory".

Note: This will only work if your script is run as a module (i.e., using the -m flag with Python, like python -m src.file2), not if you run the Python file directly (python file2.py). If you're running the file directly and the other file is in the same directory, you can just do from file1 import function1.

If you are running the file directly and the import is not working, make sure your src folder (the root folder of this module) is in the Python path. The Python path is a list of directories that Python checks when it's looking for the module you're trying to import. You can add the src folder to the Python path by adding it to the PYTHONPATH environment variable, or by adding an empty file named __init__.py in your src directory to make it a package.

helloworld
  • 613
  • 8
  • 24
-4

Just use the change directory function from the os module:

os.chdir("Here new director")

Then you can import normally.

More information

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131