You can use relative import
inside env.py, you only need from ..api.models import Base
If you don't want to use relative import, you can also try absolute import like
from be.api.models import Base
provided that you have exported the PYTHONPATH to be by
path_to_be=''
export PYTHONPATH=$path_to_be:$PATH
Answer from meTchaikovsky on Stack OverflowYou can use relative import
inside env.py, you only need from ..api.models import Base
If you don't want to use relative import, you can also try absolute import like
from be.api.models import Base
provided that you have exported the PYTHONPATH to be by
path_to_be=''
export PYTHONPATH=$path_to_be:$PATH
Some suggetions:
1.) Just accept it and modify sys.path ;-)
2.) make sure the environment variable PYTHONPATH points to the parent directory (be) and call your script only then
Example:
export PYTHONPATH=/absolute/path/to/be
3.) add an __init__.py file into the directory alembic
and call your script from the be direcrory with.
python -m alembic.env
4.) add the __init__.py like for 3.) and a small wrapper script to the be directory and call that script from be this script will then import alembic.env and call it's 'main' function.
Don't hesitate to contact me if my suggestions aren't clear enough.
I don't know your context but I often prefer 3.) and 4.) as nobody has to know about environment variables or sys path changes.
python - Import file from parent directory causes "Import by filename is not supported" - Stack Overflow
importing from parent directory
python - Importing modules from parent folder - Stack Overflow
Relative Imports
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 PYTHONPATH $PYTHONPATH:"path/to/dir"
In case you use Windows: Adding variable to path in Windows.
Or from the command line:
set PYTHONPATH=%PYTHONPATH%;C:\path\to\dir
This question has been asked so many times but I'm still not finding what I need. If I call `./run.py` everything works fine. Calling `./foo.py` results in ImportError: attempted relative import with no known parent package. The only way I've found to accomplish this is to use sys.path.append which ends up making a mess of my imports. I don't think I want to use setup tools. Is there not some way to just do an absolute import from "package"? e.g. foo.py would have `import package.l1_dir.bar`
package
|-> run.py
|-> L1_dir
|-> __init__.py
|-> bar.py
|-> L2_dir
|-> __init__.py
|-> foo.py Foo.py
from ..bar import * print("hello from foo.py") Bar.py
print("hello from bar.py") Run.py
from .L1_dir.L2_dir.foo import *
You could use relative imports (Python >= 2.5):
from ... import nib
(Whatβs New in Python 2.5) PEP 328: Absolute and Relative Imports
I posted a similar answer also to the question regarding imports from sibling packages. You can see it here.
Solution without sys.path hacks
Summary
- Wrap the code into one folder (e.g.
packaged_stuff) - Create a
pyproject.toml(older alternative:setup.py) - Pip install the package in editable state with
pip install -e <myproject_folder> - Import using
from packaged_stuff.modulename import function_name
Setup
I assume the same folder structure as in the question
.
βββ ptdraft
βββ __init__.py
βββ nib.py
βββ simulations
βββ __init__.py
βββ life
βββ __init__.py
βββ life.py
I call the . the root folder, and in my case it is located in C:\tmp\test_imports.
Steps
1) Add a pyproject.toml to the root folder
The contents of the pyproject.toml can be simply
[project]
name = "ptdraft"
version = "0.1.0"
description = "My small project"
[build-system]
build-backend = "flit_core.buildapi"
requires = ["flit_core >=3.2,<4"]
Basically "any" valid pyproject.toml would work. This is just a minimal working example, which uses flit as build backend.
2) Use a virtual environment
If you are familiar with virtual environments, activate one, and skip to the next step. Usage of virtual environments are not absolutely required, but they will really help you out in the long run (when you have more than 1 project ongoing..). The most basic steps are (run in the root folder)
- Create virtual env
python -m venv venv
- Activate virtual env
. venv/bin/activate(Linux) or./venv/Scripts/activate(Win)
- Deactivate virtual env
deactivate(Linux)
To learn more about this, just Google out "python virtualenv tutorial" or similar. You probably never need any other commands than creating, activating and deactivating.
Once you have made and activated a virtual environment, your console should give the name of the virtual environment in parenthesis
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
3) pip install your project in editable state
Install your top level package (here ptdraft) using pip. The trick is to use the -e flag when doing the install. This way it is installed in an editable state, and all the edits made to the .py files will be automatically included in the installed package. Note that the -e flag with pyproject.toml requires pip 21.3 or newer.
In the root directory, run
pip install -e . (note the dot, it stands for "current directory")
You can also see that it is installed by using pip freeze
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///home/user/projects/ptdraft
Installing build dependencies ... done
Checking if build backend supports build_editable ... done
Getting requirements to build editable ... done
Preparing editable metadata (pyproject.toml) ... done
....
Successfully built ptdraft
Installing collected packages: ptdraft
Successfully installed ptdraft-0.1.0
(venv) PS C:\tmp\test_imports> pip freeze
ptdraft==0.1.0
4) Import by prepending mainfolder to every import
In this example, the mainfolder would be ptdraft. This has the advantage that you will not run into name collisions with other module names (from python standard library or 3rd party modules).
Example Usage
nib.py
def function_from_nib():
print('I am the return value from function_from_nib!')
life.py
from ptdraft.nib import function_from_nib
if __name__ == '__main__':
function_from_nib()
Running life.py
(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!
Hello there :)
Assume, you have the following file structure:
.
βββ a
βββ a_file.py
βββ b
βββ b_file.py
In b_file, I want to import functions from a_file. Even adding __init__.py to a/ did not help.
When searching for the problem, I found that I seemingly had to add b/ to PYTHONPATH or whatever. Please tell me there is a more convenient solution.
(If there's not a nice and simple solution, I'd be really interested in why it is not possible to simply import from a parent folder while it is no problem to import from a child directory.)
I am having the classic problem with my imports. I know that this is a very common issue to run into and I am still trying to understand it, but I could use a little help.
I have a package:
. βββ my_package β βββ main.py β βββ notebooks β β βββ notebook.ipynb β βββ utils.py βββ some_file.txt
The code is mostly in main.py, which imports utils.py for some helpers. But since I am also exploring certain things before properly developing in main.py, I have also a notebooks directory. Inside here I play around with a bunch of stuff and this requires access to the code from main, utils, etc.
My problem is that I cannot import those code. If I type, from my_package import utils I receive a ModuleNotFoundError: No module named 'my_package'. If I run a from .. import utils I receive ImportError: attempted relative import with no known parent package.
Am I correct in saying that the only proper way to do this is to make a proper setup with setup.py and $ pip install -e my_package? I do not like using sys to update the path, it seems dirty. If there is a way to do this without the setup then that would be great, as wasn't intending to make it a full package as it is only a small project and I am learning.
[edit] It seems that the "proper" way would be to go with the setup.py approach, but I just found a way to update the conda environment to include this permanently which is a decent solution. Just needed to type $ conda develop path/to/my_project and it creates a conda.pth file in the conda environment's site-packages directory.