I want to have project structure as you can see below:
some API module, which i use to make some tools.
├── api
│ ├── __init__.py
│ ├── some_script.py
├── tools
│ └── tool1.py
api/some_script.py
def func():
print("Func1")
class some_object():
...
api/__init__.py
from .some_script import some_object, func
Where in tool1.py is
from ..api import func
I want that tools in folder, but I keep getting import error. To this point I had tool1.py in no folder and it worked fine (but with code
from api import func)
ImportError: attempted relative import with no known parent package
How to make it work this way?
Thanks for answers
I tried your code and got the same error, turns out you need to help the import using sys here is how to do it:
import sys
sys.path.append("..")
from api import some_script
#basic beatle
helped me solve it. With some other sources and this one works:
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
Related
I have a file structure like this:
application
├── scripts
│ └── script1.py
├── utils
│ └── util1.py
├── main.py
Now I want to be able to import util1.py from script1.py so I decided to change the directory and use imports in script1.py like so:
import sys
import os
from os.path import dirname, abspath
os.chdir(dirname(dirname((__file__))))
from utils import util1
if I were to print the current directory using os.listdir() it would show the 2 folders and main.py, however it still says that there is no module named util. Am I using the os.chdir wrongly, or is there something else wrong with my code? I would like to be able to easily access modules from the same parent directory of application without going through too much hassle, since I use quite a lot of them.
I've read many docs over the last few days about relative Python imports but run into a struggle with the following folder structure:
parent_folder
├── subfolder1
│ └── __init__.py
│ └── file_1.py
├── subfolder2
│ └── __init__.py
│ └── file_2.py
│
└ __init__.py (parent folder has an init in it)
In file_2.py I would like to access the functions in file_1.py. I've tried adding the following to file_2.py but none seem to work:
1. from ..subfolder1 import file_1 #ImportError: attempted relative import with no known parent package
2. import parent_folder.subfolder1.file_1 #ModuleNotFoundError: No module named 'parent_folder'
3. from parent_folder.subfolder1 import file_1 #ModuleNotFoundError: No module named 'parent_folder'
I'm really lost right now and can't seem to understand why this is occuring. I've probably read 10 different guides on relative imports now and still can't figure out why.
Note, if I put file_2.py inside parent_folder, and then add import subfolder1.file1 it imports well, but I can't move file_2.py from it's position or use sys.path.append()
Does anyone with more module experience than I have any insight? Thank you!
The answers advising messing with the sys path are wrong - unfortunately this advice is floating over the web causing infinite frustration and crashes (good) to subtle bugs (bad).
The correct answer is running your script using the -m switch from the parent folder of the top most package. So if this parent_folder is a package as it looks it is and you want to run file_1.py you should
$ python -m parent_folder.subfolder1.file_1
any of the three imports would work then
Change Path
Make sure you change sys.path before you start importing anything so you don't get an error when importing
So, begin with this:
import os, sys
path = os.path.join(os.path.dirname(__file__), os.pardir)
sys.path.append(path)
In my case I did this
import sys
sys.path.insert(0, '..')
then
from parent_folder.subfolder1.file_1 import --the-function-needed--
Here's my current folder structure
.
├── api
│ ├── api_routes.py
│ └── sql
│ └── models.py # import db into this file
├── application
│ └── __init__.py # db here
└── wsgi.py
In __init__.py there's a variable db (Flask-SQLAlchemy instance) and a function create_app, all of which are successfully imported into wsgi.py using this line:
from application import create_app
I used the same line to import db into models.py, to no avail. What can I do now? I have no idea where to start. One SO post suggests that maybe there's a circular import involved, however, I can't find it in my code. I also tried to import with these lines without success:
from . import create_app
from .application import create_app
from ..application import create_app
Edit: after 1 week turning a way from the problem, I found the line that causes it all. The problem was indeed circular dependency. Thanks for all your help!
There are few tricks to handle such imports,
1) Mark the "application" folder as the "Sources Root", and then I think it should work (marking folder as sources root is relatively easy when using pycharm so I suggest you to use pycharm for this and for many more tricks with python)
2) trick number to is to add the path to the directory you want to import from to sys.path, do something like
import sys
sys.path = ['/path/to/your/folder'] + sys.path
...
other code
and then importing should work.
I hope this will help (:
My project has the following structure:
.
└── mylib
├── __init__.py
├── fun1.py
├── fun2.py
└── test.py
Suppose test.py imports functions from modules fun1.py and fun2.py, so it contains
from fun1 import funA
from fun2 import funB
However, when I try to import test.py outside my project directory I get the following error:
ModuleNotFoundError: No module named 'fun1'
I can fix this by specifying the whole path to fun1.py and fun2.py in my imports.
from mylib.fun1 import funA
from mylib.fun2 import funB
But again, suppose I don't have only to import funA() and funB + I have a whole bunch of modules other than test.py that also imports functions from each other. So it would take a huge amount of time specify the path for every import (more than 200 imports made like this).
Is there a cleaner way to make these imports besides specifying the whole path for all of them?
I tried making these imports on my __init__.py, but due to my inexperience, I'm still unable to make it work.
FILES
fun1.py
def funA():
return True
fun2.py
from fun1 import funA
def funB():
return True
test.py
from fun1 import funA
from fun2 import funB
If I understand correctly, you want to have a file outside mylib that looks like
from mylib import funA
First, it seems that you need the relative imports everywhere inside mylib. Second, you need to use your __init__.py to import everything from the local directory and make it available in the directory above. I would change (minimally) your files as follows, adding some more files to test the imports.
Directory structure:
.
├── mylib
│ ├── fun1.py
│ ├── fun2.py
│ ├── __init__.py
│ └── test.py
├── scriptA.py
├── scriptB.py
└── script_test.py
fun2.py
from .fun1 import funA
def funB():
return True
__init__.py
from .fun1 import funA
from .fun2 import funB
test.py
from . import funA, funB
scriptA.py
from mylib import funA
scriptB.py
from mylib import funB
script_test.py
from mylib import test
test.funA()
You can now use script A, B, or _test as your needs require. This pattern extends to deeper directory structures as you continue to use the relative import with . in the __init__.py at each directory level.
You need to import modules/functions where you need them. There is no magic way for python to know that you have imported something. There are different ways to import needed modules/functions (https://docs.python.org/3/reference/import.html), but what I've found most useful is to import modules and then later use module name with dot syntax to call functions, so something like:
from . import func1
from . import func2
def test():
func1.funA()
func2.funB()
just an example. But you can see a general idea. (from . import func1 will import func1 from current directory/module)
Based on my understanding, you are trying to import modules that are in some other project location. Try this and replace path with the location from where you want to import modules.
sys.path.insert(0, path)
Please let me know if I misunderstood your question.
I'm trying to import a file but I can only get it to work from one context at a time.
This my project structure:
.
├── module/
│ ├── __init__.py
│ ├── script.py
│ ├── utilities1.py
│ └── utilities2.py
└── test.py
script.py is usually called externally directly it imports utilities1.py
utilities1.py imports utilities2.py
test.py Is a file that contains tests and includes both utilities1.py and utilities2.py
My question is how to do the import statement in utilities1.py
When I call it from script.py it needs to be
import utilities2
But when I call it from test.py that results in an error requiring it to be
import module.utilities2
Is there a way I can get the import statement right in both contexts?
Or do I need to change something structurally in my project?
Thank you :)
If what you want is being able to use import utilities1 from test.py you could modify the search path of modules. sys.path is the list of paths where the interpreter will look for modules to import. Do print(sys.path) and you'll see. You can also modify it while running your script.
For example, keeping with the file structure you described
# script.py
import utilities1
import utilities2
utilities1.show_myself()
utilities2.show_myself()
# utilities1.py
def show_myself():
print("I'm utilities1")
def test_myself():
print("Testing who I am... The answer: utilities1")
# utilities2.py
def show_myself():
print("I'm utilities2")
def test_myself():
print("Testing who I am... The answer: utilities2")
# test.py
import sys
sys.path.insert(1, "module")
import utilities1
import utilities2
utilities1.test_myself()
utilities2.test_myself()
In test.py I have inserted module in sys.path which is the relative path where the running script will to be looking into for modules utilities1 or utilities2. That's why it is able to acess directly yo those two modules.
If that's not what you were trying to do, please explain further.