简体   繁体   中英

How do I import an object from main.py (in the root directory), into a module contained in a subdirectory?

So, this is the project structure:

<root directory>
- app 
- - name
- - - module1
- - - module2
- - - module3
- - - - tests.py 
- test_db.py

test_db.py contains an object called client which I need in all the tests.py files in different modules.

I could simply move test_db.file inside the app directory but test_db.py needs to import app from main.py which is again in the root directory and will cause the same issue again.

In every tests.py I need something like:

from ....test_db import client

but it just gets:

from....test_db import client

E ImportError: attempted relative import beyond top-level package

So, I just can't figure out importing an object/package from the root directory.

PS: I know one simple solution would be to change the directory structure a little, but It's a large project and changing the structure would be a LOT of work. So, ideally I need some way to add the root directory to the path inside every tests.py file. Something like this:

app/name/module3/tests.py:

import sys

#sys.path.something.. I am not really familiar with how to use this

from ....test_db import client #this should import client from test_db in root instead of throwing error

def test_create_todo():
    pass

If you want to do a relative import without hacking around with sys.path or custom loaders/finders, you need:

  • the top-most directory you import relative to to contain an __init__.py
  • to specify said directory as a package in the path to your __main__ module (ie python -m root.stuff.main )

In short, this means you could add a directory project to contain the test_db.py and app , add an __init__.py , and call your program with python -m project.app.stuff.main .

If this doesn't work for you (you mention you don't want to change the project structure) you do have other options.

You could install each as its own package ( app , and tests ). Create a setup.py / setup.cfg / pyproject.toml , put test_db.py in a package tests , and pip install them as editable packages pip install -e. . This will allow you to import either without relative imports (just import app , and import tests.test_db , regardless of file). This is personally the route I would go, and recommend doing.

Otherwise, if you're just looking for a quick fix, there exists one more easy + hacky solution. You could add the path for test_db.py to sys.path (every path in this list is explored for the target module when importing), so you could import test_db from anywhere. Again, this is very hacky, and I don't recommend it beyond quick sanity checks or extremely urgent patches.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM