I have a following package structure:
project\
app\
main.py
__init__.py
lib\
funcs.py
__init__.py
When I try to import my functions from funcs.py to main.py using from lib.funcs import func1, func2 it works perfectly fine in PyCharm, but not in VS Code. In VS Code I get:
ModuleNotFoundError: No module named 'lib'
However, if I chage the structure to:
project\
main.py
lib\
funcs.py
__init__.py
it works fine in VS Code as well.
Why is that? Is there are a way to run imported code from the app package like in the first example?
I tried to play around with __init__.py files, making and unmacking different folders a packages, using the from .lib.funcs import func1, func2 and using from project.lib.funcs import func1, func2. In the first case I get:
ImportError: attempted relative import with no known parent package'
While in the second:
ModuleNotFoundError: No module named 'project'
Open launch.json and add
"env":{
"PYTHONPATH":"${workspaceFolder}"
}
In main.py, import modules like from lib import func. This solution only works when you Run without Debugging:
The second way is adding the following code before importing modules, and you don't need to add args env in launch.json
import sys
sys.path.append("./")
Clicking the green button on the top right corner to Run Python File in Terminal and Run without debugging both works.
Related
I apologize for the millionth post about this topic.
I thought I had a good grip of the whole absolute/relative import mechanism - I even replied to a couple of questions about it myself - but I'm having a problem with it and I can't figure out how to solve it.
I'm using Python 3.8.0, this is my directory structure:
project_folder
scripts/
main.py
models/
__init__.py
subfolder00/
subfolder01/
some_script.py --> contains def for some_function
I need to import some_function from some_script.py when running main.py, so I tried:
1) relative import
# in main.py
from ..models.subfolder00.subfolder01.somescript import some_function
but when I run (from the scripts/ folder)
python main.py
this fails with error:
ImportError: attempted relative import with no known parent package
This was expected, because I'm running main.py directly as a script, so its _name_ is set to _main_ and relative imports are bound to fail.
However, I was expecting it to work when running (always from within the scripts folder):
python -m main
but I'm getting always the same error.
2) absolute import
I tried changing the import in main.py to:
# in main.py
from models.subfolder00.subfolder01.somescript import some_function
and running, this time from the main project folder:
python scripts/main.py
so that - I was assuming - the starting point for the absolute import would be the project folder itself, from which it could get to models/....
But now I'm getting the error:
ModuleNotFoundError: No module named 'models'
Why didn't it work when using the -m option in the case of relative import, and it's not working when using absolute ones either? Which is the correct way to do this?
I think quite likely you missed python's official doc ( that even come offline )
https://docs.python.org/3/tutorial/modules.html
you'll need a dummy __init__.py within your module, at same level of some_script.py
I think your "absolute" import may not have been absolute in the truest sense.
Prior to running the python scripts/main.py command, you would have needed to setup PYTHONPATH environment variable to include the path to project_folder.
Alternatively I do something like this in main.py:
import sys
import os
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','models','subfolder00','subfolder01'))
from somescript import some_function
Maybe it is a little pedantic, but it makes sense to me.
I am building on AWS CodeBuild using Python 2.7, but I believe this is much more a generic python import problem. I have a directory setting, shown below. I am running test.py inside the test folder. I would like to import the dependency mainScript.py as part of this testing. However, I cannot seem to get the relative dependencies right and I am having a lot of difficulty importing the mainScript within the test folder. Below is a layout of my directory folder
main
src
mainScript.py
test
test.py
If for example my directory setup was something like
main
test
test.py
mainScript.py
I could have my import be done the following way
from mainScript import *
I have confirmed this works. But, I like it in its own src folder. I have tried all these These are the following relative path attempts I have tried
from ..src/mainScript import * #SyntaxError: invalid syntax
from ..src.mainScript import * #ValueError: attempted relative import beyond top-level package
from mainScript import * #ModuleNotFoundError: No module named 'mainScript'
from src.mainScript import * #ModuleNotFoundError: No module named 'src'
from src/mainScript import * #SyntaxError: invalid syntax
I have been struggling for a bit and I couldn't quite find a question with someone asking about accessing a brother/sister folder script. Thank you in advance for your help.
Python treats directories as packages if they contain a __init__.py file. Updating your structure to the following should do the trick:
__init__.py
src
__init__.py
mainScript.py
test
__init__.py
test.py
Now, from test.py, you could do from ..src import *. For more details on init.py, you can look here: What is __init__.py for?
In addition to adding the init.py files. It ended up being that I had to run python with the -m argument in my command, which was added in Python 2.4.
PEP 338
Python 2.4 adds the command line switch -m to allow modules to be
located using the Python module namespace for execution as scripts.
The motivating examples were standard library modules such as pdb and
profile, and the Python 2.4 implementation is fine for this limited
purpose.
So the command to launch from the top directory is:
python -m test.test
This seems to work and get the right namespace. Then in your test.py file you would import the mainScript the following way
from src.mainScript import *
Here we go with my first ever stackoverflow quesion. I did search for an answer, but couldn't find a clear one. Here's the situation. I've got a structure like this:
myapp
package/
__init.py__
main.py
mod1.py
mod2.py
Now, in this scenario, from main.py I am importing mod1.py, which also needs to be imported by mod2.py. Everything works fine, my imports look like this:
main.py:
from mod1 import Class1
mod2.py:
from mod1 import Class1
However, I need to move my main.py to the main folder structure, like this:
myapp
main.py
package/
__init.py__
mod1.py
mod2.py
And now what happens is that of course I need to change the way I import mod1 inside main.py:
from package.mod1 import Class1
However, what also happens is that in order not to get an "ImportError: No module named 'mod1'", I have make the same type of change inside mod2.py:
from package.mod1 import Class1
Why is that? mod2 is in the same folder/pakcage as mod1, so why - upon modifying main.py - am I expected to modify my import inside mod2?
The reason this is happening is because how python looks for modules and packages when you run a python script as the __main__ script.
When you run python main.py, python will add the parent directory of main.py to the pythonpath, meaning packages and modules within the directory will be importable. When you moved main.py, you changed the directory that was added to the pythonpath.
Generally, you don't want to rely on this mechanism for importing your modules, because it doesn't allow you to move your script and your package and modules are only importable when running that main script. What you should do is make sure your package is installed into a directory that is already in the pythonpath. There are several ways of doing this, but the most common is to create a setup.py script and actually install your python package for the python installation on your computer.
I'm starting a project in python, the code structure now as below:
project/
__init__.py
a.py
b.py
mainA.py
utilities/
__init__.py
mainB.py
c.py
The __init__ files are all blank.
I want to run utilities/mainB.py as a program(using something like python main.py), and mainB needs to import a.py and b.py. So I tried from .. import a and some other approaches, but the import failed. The error information is:
ValueError: Attempted relative import in non-package
So here comes the questions:
how to fix mainB.py so it can be run as a main program?
mainA.py can be run as main program now, it also imports a.py and b.py(using import a and import b).
I think the code structure may become more complex. Say, if mainA.py has to import a module from project/some/directory, how can I do that?
See this previous question. You have two options. One is to use the __package__ attribute as described in PEP 366 to set the relative name of your modules. The other is to execute your scripts as modules (using the -m flag to the interpreter) instead of running them directly as scripts.
You could use Python's built-in module-running functionality (python -m <module>).
python -m project.utilities.mainB
This allows you to write mainB normally as part of the package, so relative and absolute imports will both work correctly.
For an in-depth discussion of this functionality, see PEP-338.
You should add 'project' dir in PYTHON_PATH and then, in mainB.py:
from project import a
I have a project structure something like this...
/some_app
build/
README
out.py
some_app/
__init__.py
mod1.py
mod2.py
Now I want to import some_app package into mod2, without messing with sys.path trickery. What I simply did is...
# mod2.py
import some_app
Now when I run the mod2.py from the command line
some_app $ python mod2.py
it throws error ImportError: No module named some_app
BUT, inside the out.py file, when I do
# out.py
import some_app.mod2
and then do
some_app $ python out.py
it runs perfectly.
Hence, what is happening is this. I load a package in a module that is within the same package, and then run that module as the __main__ file -- and it doesn't work. Next, I load the same module (the one that I ran as __main__) inside another module, and then run that another module as __main__ -- and it works.
Can someone please elaborate on what's going on here?
UPDATE
I understand that there is no straightforward reason for doing this -- because I could have directly imported any modules inside the some_app package. The reason I am trying this is because, in the Django project, this is what they're doing. See this file for example
In every module, all the non-standard imports start with django.. So I wondered why and how they are doing that.
UPDATE 2
Relevant links
How to do relative imports in Python?
Python: import the containing package
mod2.py is part of some_app. As such, it makes no sense to import the module, since you're already inside it.
You can still import mod1. I'm assuming you need some_app/__init__.py to run. Not sure that's possible.
EDIT:
Looks like from . import some_module will do what you're after.
You can do import some_app.mod2 from out.py because it is in the same directory that you have some_app package, and Python interpreter starts to look for modules from that path.
The import error in mod2.py is normal because there is not a some_app package in mod2.py folder.
It seems like "from . import some_module" works in Python3 only.
The universal way is to do all imports in init.py