Importing from a file in previous path in python - python

I have this file structure:
.
test/db_test.py
models/user.py
I want to import user.py in db_test.py, for example i try it:
from ..models.user import User
but have this error:
SystemError: Parent module '' not loaded, cannot perform relative import
How can do this work?
all path have __init__.py file
i don't want to use appending in sys.path
thank for your answers

Have you tried running the script as a package? Try running the following from the directory containing your package root directory:
python -m your_package_name.test.db_test
My test that this worked for was:
your_package_name/
__init__.py
test/
__init__.py
db_test.py
models/
__init__.py
user.py
Where "db_test.py" contained:
from ..models.user import User
So I ran that command from the parent directory of "your_package_name".

Related

Python: How to import file from subdirectory of parent of parentdirectory?

How can I import file from subdirectory of parent of parentdirectory? I know that this doesn't make sense so let me explain. I want to import the file test.py into the file example.py.
Here is the directory structure:
directory1
+-- directory2
+-- test.py
+-- directory3
+-- directory4
+-- example.py
Add __init__.py file inside each directory, parent directory and subdirectories
parent/
__init__.py
package_1/
__init__.py
package_2/
__init__.py
package_3/
__init__.py
from parent.package_1 import ....
If doesn't work, try to configure PYTHONPATH, in case of IDE like PyCharm, there's a flag (checkbox) in run/debug configuration
or you might add module to the default path using sys.path.insert(...)
import sys
sys.path.insert(0, module_full_path)
You could check path, using print(sys.path)
Just make sure folder also contains an __init__.py, this allows it to be included as a package
You have serveral options:
Like the comment said you can use a full path:
/home/User/directory1/directory2/test.py
Map that file to a variable and use it. (Watch out with using python built in names like test)
use os.chdir and change your dir to the root of you directory1 and call directory2/test.py
make an init.py and use it as a package with the from [directory] import [module]
Here you go =^..^=
from pathlib import Path
import sys
path = Path(__file__).parents
sys.path.append(str(path[2] / 'directory2'))
import test

Import class from another subfolder

There are lots of similar questions, but none of them seem to help me with this.
I have the following file structure:
rest_api
__init__.py
utils
__init__.py
config.py
foo
__init__.py
foo.py
I'd like to import the Config class from config.py, into foo.py. I attempt to run:
pipenv run python rest_api/foo/foo.py
I have tried numerous things, including adding the parent folder to PATH and using relative imports, but the import line always fails:
from rest_api.utils.config import Config
I get the following error:
ModuleNotFoundError: No module named 'rest_api'
I should mention that the __init__.py files are all empty. Not sure if they are neccessary, since I have Python 3.8.2.

Python - ModuleNotFoundError: No module named

I'm new in Python and I'm having the following error with this simple example:
This is my project structure:
python_project
.
├── lib
│   ├── __init__.py
│   └── my_custom_lib.py
└── src
├── __init__.py
└── main.py
And this is the error when I execute the src/main.py file:
☁ python_project python src/main.py
Traceback (most recent call last):
File "src/main.py", line 3, in <module>
from lib import my_custom_lib
ImportError: No module named lib
If I move the main.py file to the root and then I execute this file again, works... but is not working inside src/ directory
This is my main.py:
from lib import my_custom_lib
def do_something(message):
my_custom_lib.show(message)
do_something('Hello World!')
Note: When I execute the same code from Pycharm is working fine, but not from my terminal.
Your PYTHONPATH is set to the parent directory of the executed script. So if the executed script is inside a directory src, it will never be able to find the sister directory lib because it isn't within the path. There's a few choices;
Just move lib/ into src/ if it belongs to your code. If it's an external package, it should be pip installed.
Have a top-level script outside of src/ that imports and runs src.main. This will add the top-level directory to python path.
In src/main.py modify sys.path to include the top-level directory. This is usually frowned upon.
Invoke src/main.py as a module with python -m src.main which will add the top-level directory to the python path. Kind of annoying to type, plus you'll need to change all your imports.
If I may add to MarkM's answer, if you wanted to keep your current directory structure and still make it work, you could add a setup.py in your root dir, where you can use setuptools to create a package you could install.
If your file had something along the lines of:
# setup.py
from setuptools import find_packages, setup
setup(
name='foo',
version=`1.0.0`,
packages=find_packages(),
entrypoints={
'console_scripts': [
'foo=src.main:main',
],
},
)
And then you do pip install [--user] -e path/to/directory you'll get an "editable package" which will effectively a symlink to the package in your development directory, so any changes you make will not require a reinstall (unless of course you rejig package structure or add/remove/edit entry points).
This does assume your src/main.py has a main function.
You'll also need __init__.py files in your "package" directories, even in Python3, as otherwise Python assumes these are namespace packages (Won't go into detail) and the find_packages() call won't find them.
This will also allow your relative imports to work. Absolute imports will only work when invoking the script from your entry point but not when calling the script directly in your development directory.
You should have your main.py script above all python packages in your directory structure. Try to update your project to the following structure:
.
|__ main.py
|__ lib
| |__ __init__.py
| |__ your_custom_lib.py
|__ another_python_package
|__ __init__.py
|__ another_python_scripts
After that, python main.py in your project directory will work.
You are using the from a import b incorrectly. it should look like this:
import lib.my_custom_lib
The other method is used to import certain methods, functions, and classes from a module, not the module itself. To import a specific function from the my_custom_lib module it would look like this:
from lib.my_custom_lib import foo
Try using a relative import instead:
from ..lib import my_custom_lib
in my case in visual code
actual error in line 1
I didn't imported _typeshed module but by default it was their
so delete that module if you found in line 1
MarkM's answer is still excellent; I'm using PyPi now. I attempted to disambiguate what he was saying about "current directory". In case my confusion was an intended feature, here is how I did it.
vagrant#testrunner:~/pypath$ tree
.
├── proga
│   └── script1.py
└── progb
└── script1.py
script1.py is the same in both directories:
#!/usr/bin/env python3
import sys
print(sys.path)
Where I run it from makes no difference, PYTHONPATH prepends the directory containing the script I specify:
vagrant#testrunner:~/pypath/proga$ ./script1.py
['/home/vagrant/pypath/proga', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/vagrant/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']
vagrant#testrunner:~/pypath/proga$ ../progb/script1.py
['/home/vagrant/pypath/progb', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/vagrant/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']
For me importing with explicit paths works best in such situations. If you need to go up in the tree use '..'. The plumbing is a bit cumbersome, but it always works.
path = os.path.abspath(os.path.join(pathlib.Path(__file__).parent.absolute(), '..', 'subdir', 'myFile.py'))
loader = importlib.machinery.SourceFileLoader('myFile', path)
spec = importlib.util.spec_from_loader('myFile', loader)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# now use the module:
module.myMethod()
myClassInstance = module.myClass()

Python 3 - ImportError: No module named

Situation:
Given this project structure:
project/
app/
__init__.py (empty)
stamp.py
tests/
test.py
main.py
In main.py and test.py I am trying to import the functionality of stamp.py via:
from app.stamp import Timestamp
Timestamp gets imported in main.py but not in test.py where I get this error:
ImportError: No module named 'app'
Question:
How can I in python 3.5 import functionality of stamp.py in test.py?
make sure your folder tests contains __init__.py
Below code appends the path of your project project to sys.path in test.py
python will go through to search the modules and files in your project
import sys
sys.path.append("/path/to/project")
from app.stamp import Timestamp
Make sure project/ is in your PYTHONPATH, put and __init__.py file in the project/ directory and then you will be able to call from project.app.stamp import Timestamp.

Using sys.path.insert without explicit absolute path

New to using sys.path to enable module import from another directory, so I'm sure this is a noob question but:
Is it possible to not have to use the full/explicit or absolute file path when using sys.path to access a Python script in another directory, but instead, to only provide the directory path that's local to the module file structure?
Currently, I have the following directory structure:
MyModule/
NAME/
__init__.py
bin/
userinfo.py
__init__.py
docs/
setup.py
tests/
NAME_tests.py
__init__.py
Within the setup.py file, I have it import the userinfo.py script, which just asks the users for some info during installation. In the setup.py file, the lines that call the userinfo.py script look like this:
import sys
sys.path.insert(0, '/Users/malvin/PythonDev/projects/MyModule/bin')
import userinfo
This works fine, because I know the entire file path where the userinfo.py file is, but obviously this doesn't work for someone who's trying to install the module because (obviously) there's no way to anticipate the file path on the user's system.
My question: Is there a method wherein I can import the userinfo.py file (which lives in the /bin folder) without having the entire system file path (that goes all the way up to /Users) ? In other words, I'd like to just have something like:
import sys
sys.path.insert(0, 'MyModule/bin')
import userinfo
But I know this doesn't work.
You can use the dot (./) notation for the current working directory to establish a relative path.
For example:
(syspathinsert)macbook:syspathinsert joeyoung$ pwd
/Users/joeyoung/web/stackoverflow/syspathinsert
(syspathinsert)macbook:syspathinsert joeyoung$ tree
.
├── MyModule.py
└── bin
├── userinfo.py
└── userinfo.pyc
1 directory, 3 files
(syspathinsert)macbook:syspathinsert joeyoung$ cat ./bin/userinfo.py
def say_hello():
print "hello there"
(syspathinsert)macbook:syspathinsert joeyoung$ cat MyModule.py
import sys
sys.path.insert(0, './bin')
import userinfo
userinfo.say_hello()
(syspathinsert)macbook:syspathinsert joeyoung$ python MyModule.py
hello there

Categories

Resources