I have a python application with the following directory structure:
src
|
+---- main
|
+---- util
|
+---- gen_py
|
+---- lib
In the package main, I have a python module named MyServer.py which has an import statement like:
from gen_py.lib import MyService
In order for this statement to work, I placed the following line at the beginning of MyServer.py:
import sys
sys.path.append('../gen_py/lib')
When I run MyServer.py in the terminal, I get the following error:
ImportError: No module named gen_py.lib
What I am missing here?
Your modification of sys.path assumes the current working directory is always in main/. This is not the case. Instead, just add the parent directory to sys.path:
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import gen_py.lib
Don't forget to include a file __init__.py in gen_py and lib - otherwise, they won't be recognized as Python modules.
For the Python module import to work, you must have "src" in your path, not "gen_py/lib".
When processing an import like import gen_py.lib, it looks for a module gen_py, then looks for a submodule lib.
As the module gen_py won't be in "../gen_py/lib" (it'll be in ".."), the path you added will do nothing to help the import process.
Depending on where you're running it from, try adding the relative path to the "src" folder. Perhaps it's sys.path.append('..'). You might also have success running the script while inside the src folder directly, via relative paths like python main/MyServer.py
from ..gen_py.lib import MyService
or
from main.gen_py.lib import MyService
Make sure you have a (at least empty) __init__.py file on each directory.
make sure to include __init__.py, which makes Python know that those directories containpackages
This is if you are building a package and you are finding error in imports. I learnt it the hard way.The answer isn't to add the package to python path or to do it programatically (what if your module gets installed and your command adds it again?) thats a bad way.
The right thing to do is:
1) Use virtualenv pyvenv-3.4 or something similar
2) Activate the development mode - $python setup.py develop
Make sure if root project directory is coming up in sys.path output.
If not, please add path of root project directory to sys.path.
Related
I have this for the layout of my project:
projectFolder /
setup/
__init__.py
setup.py
Utils /
__init__.py
cloudmanager.py
startup.py
I am trying to import the Setup Module inside my cloudmanager.py script (which is nested in one more directory). I can easily import both the setup module and the Utils module inside my startup.py script since it's in the root directory.
I've tried (inside my cloudmanager.py script):
from . import setup
Which gives me the error of:
ImportError: cannot import name 'setup' from partially initialized module 'Utils' (most likely due to a circular import)
and I've tried:
from .. import setup
Which gives me the error of:
ValueError: attempted relative import beyond top-level package
Any help? There are questions like this out there but they steer towards to using OS, which I'd like to avoid...
Okay, so the reason you're getting an error importing .. setup is indeed that you can't do relative imports when the parent directory is a package. A package is any directory with a __init__.py file in it.
You could solve this by doing one of two things:
You could make sure the root of your project is in the Python path and import everything in the root.
You could make your project's root directory itself a package and then use relative imports.
Option 1: Importing from the project root
If your projectFolder folder lives at /home/you/projects/projectFolder, make sure your PYTHONPATH has /home/you/projects/projectFolder in it. For example, when you run your main script, you could set it before hand. In bash (assuming a Unix environment):
export PYTHONPATH=/home/you/projects/projectFolder
python /home/you/projects/projectFolder/startup.py
You could also do that inside startup.py, if you want to avoid changing the external environment:
# startup.py
import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__)))
If you do that in startup.py, the directory of startup.py will always be in the Python path.
Once you one of those, you can base all your imports on the relative location of your project. Eg:
import setup.setup
import Utils.cloudmanager
(That will work in every file you import after the sys.path mutation runs)
Option 2: Relative imports
If you make your project's root a Python package, you can use relative imports entirely. Eg, you'd have these files:
projectFolder/__init__.py
projectFOlder/setup/__init__.py
projectFolder/setup/setup.py
projectFolder/Utils/__init__.py
projectFolder/Utils/cloudmanager.py
If you do that, inside cloudmanager.py, you could run from .. import setup just fine.
What do you do?
Both of these are valid options. In general relative imports have less ambiguity, since they avoid name collisions, but they're a newer feature of Python so option #1 is more common, in general.
Try to use:
import setup.setup
I am working on some python project (2.7) and I have issue with imports. When I run main.py it start scripts from tests folder etc. and save output to logs and everything works fine.
/root------------
-logs
-staticCfg
-config.py
-tests
-systemTest
-scrypt1.py
-scrypt2.py
-userTest
-uScrypt1.py
main.py
My static variables (email, name etc.) are located in config.py. I need to import config.py in scrypt1.py or scrypt2.py. I tryed adding __init__.py to tests, systemTest and staticCfg folder but I always get an error.
In my scrypt1.py:
import staticCfg as cfg
...
or
from staticCfg import *
...
I get the error:
ImportError: No module named staticCfg
The import mechanism of Python can be a bit tricky.
You can refer to the documentation for more information: Python Import Mechanism
When you use absolute imports (your import does not start with a .) as you do, the import path will start from your main script (the one you launch). In your case, it's scrypt1.py. So starting from this location, python can't find the package staticCfg.
For me, the simplest solution is to create a main script in your root directory and call scrypt1.py from there (imported using from tests.systemTet import scrypt1.py). In this case, the base package will be your root folder and you will have access to the package staticCfg from all your script files as you wanted to do.
you may add root folder to PYTHONPATH.
I have the following directory structure:
app/
bin/
script1.py
script2.py
lib/
module1/
__init__.py
module1a.py
module1b.py
__init__.py
module2.py
Dockerfile
My problem is that I want to execute script1.py and script2.py, but inside those scripts, I want to import the modules in lib/.
I run my scripts from the root app/ directory (i.e. adjacent to Dockerfile) by simply executing python bin/script1.py. When I import modules into my scripts using from lib.module1 import module1a, I get ImportError: No module named lib.module1. When I try to import using relative imports, such as from ..lib.module1 import module1a, I get ValueError: Attempted relative import in non-package.
When I simply fire up the interpreter and run import lib.module1 or something, I have no issues.
How can I get this to work?
In general, you need __init__.py under app and bin, then you can do a relative import, but that expects a package
If you would structure your python code as python package (egg/wheel) then you could also define an entry point, that would become your /bin/ file post install.
here is an example of a package - https://python-packaging.readthedocs.io/en/latest/minimal.html
and this blog explains entry points quite well - https://chriswarrick.com/blog/2014/09/15/python-apps-the-right-way-entry_points-and-scripts/
if so, that way you could just do python setup.py install on your package and then have those entry points available within your PATH, as part of that you would start to structure your code in a way that would not create import issues.
You can add to the Python path at runtime in script1.py:
import sys
sys.path.insert(0, '/path/to/your/app/')
import lib.module1.module1a
you have to add current dir to python path.
use export in terminal
or sys.path.insert in your python script both are ok
I have the following directory structure:
application
tests
main.py
main.py
application/main.py contains some functions.
tests/main.py will contain my tests for these functions but I can't import the top level main.py. I get the following error:
ImportError: Import by filename is not supported.
I am attempting to import using the following syntax:
import main
What am I doing wrong?
If you'd like your script to be more portable, consider finding the parent directory automatically:
import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# import ../db.py
import db
You must add the application dir to your path:
import sys
sys.path.append("/path/to/dir")
from app import object
Or from shell:
setenv PATH $PATH:"path/to/dir"
In case you use windows:
Adding variable to path in windows.
Or from the command line:
set PATH=%PATH%;C:\path\to\dir
Please mind the diff between PYTHONPATH, PATH, sys.path.
Late to the party - most other answers here are not correct unfortunately - apart LennartRegebro's (and BrenBarn's) which is incomplete. For the benefit of future readers - the OP should, first of all, add the __init__.py files as in
root
application
__init__.py
main.py
tests
__init__.py
main.py
then:
$ cd root
$ python -m application.tests.main
or
$ cd application
$ python -m tests.main
Running a script directly from inside its package is an antipattern - the correct way is running with the -m switch from the parent directory of the root package - this way all packages are detected and relative/absolute imports work as expected.
First of all you need to make your directories into packages, by adding __init__.py files:
application
tests
__init__.py
main.py
__init__.py
main.py
Then you should make sure that the directory above application is on sys.path. There are many ways to do that, like making the application infto a package and installing it, or just executing things in the right folder etc.
Then your imports will work.
You cannot import things from parent/sibling directories as such. You can only import things from directories on the system path, or the current directory, or subdirectories within a package. Since you have no __init__.py files, your files do not form a package, and you can only import them by placing them on the system path.
To import a file in a different subdirectory of the parent directory, try something like this:
sys.path.append(os.path.abspath('../other_sub_dir'))
import filename_without_py_extension
Edit: Missing closing bracket.
in python . exists for same directory, .. for parent directory
to import a file from parent directory you can use ..
from .. import filename (without .py extension)
I know this is a dumb question but i'm stumped. My directory structure used to look like this:
-src
|
-module.py
-program.py
when this what my directory structure, I referenced module from program and all was well.
I've since changed my directory structure to this:
-src
|
-__init.py
-module.py
|
-programDir
|
-__init.py
-program.py
now, of course, I can't reach the module from program. How can I reference src as a package. I tried to create an
__init__.py
file in the src directory, but no luck.
Moar deets:
import statements i've tried in program.py:
import module
and
from src import module
the first one worked when the other module and program were in the same directory.
error i'm getting:
ImportError: No module named module
and just for the record: No, my module and program are not called module OR program
update: I've tried this in my program.py file:
from ...src import module
and
from ..src import module
both are giving me:
ValueError: Attempted relative import in non-package
For starters, I recommend reading the entry Modifying Python's Search Path in the docs.
It might be frowned upon by some, but if you wish to modify the PYTHONPATH from within your program, according to the documentation's standard modules entry you can use the sys.path.append method:
import sys
sys.path.append('..')
import module
Couldn't you use PEP 328 to solve this?
If you run program.py directly, with python program.py or with #!, then module.py's directory should be in the PYTHONPATH for import module to work. This can be achieved using a helper shell script that's kept in programDir, for instance, and looks something like:
#!/bin/bash
script_dir=`dirname $0`
# Add the script's parent directory to the PYTHONPATH
export PYTHONPATH=$PYTHONPATH:$script_dir/..
python $script_dir/program.py
Another, probably better, way would be to have program.py export a "main()" function, and create a helper python script at src/program that looks like:
#!/usr/bin/env python
from programDir.program import main
main()
In this case, you can use relative imports in src/programDir/program.py, so this should work:
from .. import module
The first one worked because Python's sys.path's first entry is '' which means it will look for module names in the current working directory from which you've executed the Python interpreter.
The issue you seem to have is that the directory located at src is not set on your PYTHONPATH. So, you can do is set the PYTHONPATH environment variable explicitly.
Here's an example using bash:
export PYTHONPATH=PATH_TO_SRC:${PYTHONPATH}
then run your program as normal
Another approach is that you can explicitly set sys.path by appending to it upon execution of your program.
So, in your program.py, you would have:
if __name__ == '__main__':
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
your_main_function()
Lastly, for serious python development, you should consider virtualenv and virtualenvwrapper as it will take care of most of these things for you.
You need to add __init__.py to /programDir to interpret the directory as a package. Once a package, you can import the package's contents.
So, in your case, if /src is on the PYTHONPATH, from module.py you can import program.py with from programDir import program.
If you use program as part of a package, in another python module, such as
import src.programDir.program as p
p.some_method()
you can use relative import in program.py, assuming you are creating a package with src (__init__.py in both src and programDir)
from .. import module
If not, for example you are calling program.py from the command line, you must add the directory containing src to your search path either by modifying sys.path or the PYTHONPATH env var, before importing.