1

Let's assume I have two parallel directories, with simple python files.

  • 'dir_one' with file_one.py
  • 'dir_two' with file_two.py

In file_one.py there is a function named function_one. How can I import it in file_two.py?

I have checked literally a few dozens of sources, including answers on stackoverflow. Therefore, I am not quoting any of them here. I have tried four different solutions, none of them worked:

  1. Insert 'init.py' files in all the directories - results in error 'ImportError: attempted relative import with no known parent package'
  2. Make both directories a single package - not possible in this case, directories have to be able to run as independent apps.
  3. Use sys module: sys.path.insert(0, 'path-to-dir_one') right before 'import dir_one' line - doesn't change anything, still get 'ModuleNotFoundError: No module named 'dir_one'.
  4. try relative import: 'from .dir_one import file_one' - 'ModuleNotFoundError: No module named 'zweizen.prodalitics'.

Is it possible at all to import a function in python from parallel folder without making it part of the same package?

2
  • 1
    The conventional way to do this would be to add the to dir_one as a dependency to the dir_two package metadata. All modern package managers (uv, Poetry …) should support this, and even pip does. — The upshot is: you would install the dir_one package in the environment of dir_two. You can use an “editable” dependency if you want to be able to see edits to dir_one “live” in dir_two. Commented Sep 27, 2024 at 12:17
  • 1
    "directories have to be able to run as independent apps" It is a strange requirement to let independent apps touch each other's code. You generally shouldn't do it. Commented Sep 27, 2024 at 13:18

3 Answers 3

1

You can add directly load the module to sys.modules using importlib to import it. I assume you are working with a directory structure similar to this.

Directory Structure

file1.py

a = 10

file2.py


import os

def import_from_path(module_name:str, file_path: str):
    import importlib.util
    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

file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../dir1/file1.py'))
module_name = "file1"

file1 = import_from_path(module_name, file_path)

print(file1.a)

You can import any python file as a module using this method and you don't modify the system path too.

Sign up to request clarification or add additional context in comments.

1 Comment

Works! Another solution which worked was via importmonkey (pip install importmonkey; from importmonkey import add_path; add_path("../src/project") ; import mymodule). I like Vignesh suggestion more, as I do not have to rely on external module.
0

Just add "dir_one" to the Python path.

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

from dir_one import func_one

1 Comment

See my comment on the existing answer which provides the same solution (but much more detail and context).
-1

⚠️ WARNING: Applications should never need to hack the sys.path. If you need to modify it, do it via a wrapper (the way e.g. pytest does it), not in the project code itself. If you do this your application now hard-codes a package path to something outside its file system which is incredibly brittle and just generally a terrible idea.

With that out of the way, here is a minimum reproducible example showing that your number 3 approach, which involves doing a "hack" where you modify the system path at runtime, should work.

Say you have the following directory structure:

project/
│
├── dir_one/
│   └── file_one.py
│
└── dir_two/
    └── file_two.py

With the content of dir_one/file_one.py:

def function_one():
  return 'Hello from function_one in file_one!'

You can add the path of dir_one to sys.path so python knows where to find file_one in dir_two/file_two.py:

import sys
import os

dir_one_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'dir_one'))
sys.path.insert(0, dir_one_path)

from file_one import function_one

if __name__ == '__main__':
  print(function_one())

Output from running python file_two.py from within project/dir_two:

Hello from function_one in file_one!

3 Comments

Applications should never need to hack the sys.path. If you need to modify it, do it via a wrapper (the way e.g. pytest does it), not in the project code itself. Your application now hard-codes a package path to something outside of its file system. That’s incredibly brittle and just generally a terrible idea.
Got it just wanted to try write a minimum reproducible example proving it was possible.
They don't teach you how to write minimum reproducible examples like this in school. It's a lost art which I'm trying to practice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.