Reputation: 24926
I want to import a function from another file in the same directory.
Usually, one of the following works:
from .mymodule import myfunction
from mymodule import myfunction
...but the other one gives me one of these errors:
ImportError: attempted relative import with no known parent package
ModuleNotFoundError: No module named 'mymodule'
SystemError: Parent module '' not loaded, cannot perform relative import
Why is this?
Upvotes: 1837
Views: 2095600
Reputation: 53065
Let's imagine you have this directory structure:
dev/
my_project/
config.py
sandbox/
test.py
And you want to cd
into my_project
and run test.py
, where test.py
imports config.py
. Python doesn't allow this by default: you cannot import anything from above your current directory, unless you use sys.path.insert()
to insert that upper directory into your system path first, before attempting the import.
So, here's the call you want to make:
cd dev/my_project
./sandbox/test.py
And here's how to allow test.py
to import config.py
from one directory up:
test.py:
#!/usr/bin/env python3
import os
import sys
# See: https://stackoverflow.com/a/74800814/4561887
FULL_PATH_TO_SCRIPT = os.path.abspath(__file__)
SCRIPT_DIRECTORY = str(os.path.dirname(FULL_PATH_TO_SCRIPT))
SCRIPT_PARENT_DIRECTORY = str(os.path.dirname(SCRIPT_DIRECTORY))
# allow imports from one directory up by adding the parent directory to the
# system path
sys.path.insert(0, f"{SCRIPT_PARENT_DIRECTORY}")
# Now you can import `config.py` from one dir up, directly!
import config
# The rest of your imports go here...
# The rest of your code goes here...
if [ "$__name__" = "__main__" ]
, relative imports are more natural, and are done as follows:
Upvotes: 1
Reputation: 11469
I had a similar problem and solved it by creating a symbolic link to the package in the working directory:
Linux
ln -s ../../../my_package my_package
Windows PS (as elevated)
New-Item -Path "my_package" -ItemType SymbolicLink -Target "my_package
and then import it as usual
import my_package
Upvotes: -2
Reputation: 19
I tried @goffer's solution:
if __name__ == '__main__':
from mymodule import as_int
else:
from .mymodule import as_int
and it works for some cases, but still fails for some other cases, then I changed it to follow Python's try/except philosophy :
try:
from mymodule import as_int
except ImportError:
from .mymodule import as_int
Then it is working pretty good.
Upvotes: -1
Reputation: 61
I had this issue because of a misunderstanding in setup.py You might not ever need this answer but while using setup.py to install my package from a folder I had this configuration:
packages=setuptools.find_packages(include=["package_folder.*"])
This is wrong as it was not supposed to have
.*
And should have been:
packages=setuptools.find_packages(include=["package_folder"])
It's just that the package was not installed properly, a deviation from relative imports.
Upvotes: 0
Reputation: 2200
It's good to note that sometimes the cache causes of all it.
I've tried different things after re-arranging classes into new directories, and relative import started to work after I removed the __pycache__
.
Upvotes: 4
Reputation: 13
As this topic is still very unclear for most of us: aka 'how more complex scenario would work in-terms of relative imports in Python' (when your module is not just one .py-script in a folder, but N-classes grouped in more complex folder-hierarchy, like more complex modules often are.). Tbh, I think it does not, or at least everything related to that particular problem is so vaguely told, explained and documented online, that it is really difficult to understand how do it even nearly "right" or similar to for example C# namespaces.
So, as there are many good answers already to relative imports in more simple modules, I would like to give a shout on this to show a bullet-proof(ish) way & show the potential "blocker" to get your custom package with more complex modules to provide relative import internally (taken developing your own python program with >script-complexity), as there are some claims that Python3.3+ would handle these without __init__()
files and so on. I found that claim partly false, as I tried all the given tricks (regarding use of relative, not absolute path)).
So, lets begin:
In order to enable relative references between package's N modules, you do need at least one(1) __init__.py
file that defines the visibility to your custom modules.
Example:
in order to solve relative imports for good between N custom modules implemented to your custom package:
Logic that applies when wanting to enable relative imports such as defined above:
Taken the package and its modules are something like below:
`
<path to>/custom_package_folder
<path to>/custom_package_folder/my_module_a/my_custom_manager.py
<path to>/custom_package_folder/my_module_b/folder_x/subfolder_y/my_class_x.py
<path to>/custom_package_folder/my_module_n
`
At the /custom_package_folder:
Add:
`
__init__.py
`
And in __init__.py
add:
`
from . import my_module_a
from . import my_module_b
from . import my_module_n
`
Now taken that the 'my_module_a/my_custom_manager.py':
`
class my_custom_manager():
def my_func():
print("message from module_a my_custom_manager class")
`
Now, you can access any custom module made visible for your package as demonstrated above, without need for absolute paths (or even sys/os cwd
magic).
For example if we run: 'my_module_b/folder_x/subfolder/my_class_x.py':
`
# import any class from my_module_<N> via relative referencing made
# possible by offering visibility via your package's __init__.py
from my_module_a import my_custom_manager
mr_man = my_custom_manager()
mr_man.my_func()
`
>>> 'message from module_a my_custom_manager class'
Why the above works is that visibility between our two own modules (a,b) has been granted via package's __init__.py
configuration that allows the separate modules see each other.
If you're building any larger package/software in Python, there is no real reason to not manage properly these allowances/restrictions of the visibility properly anyway, as that is what they are (for designing / implementing higher level software architecture).
Note 1: I have found it really easy-when the program includes more modules, or modules include N classes, to build the software in a 'V'-flow, where objects in the same hierarchy-level of the program never access each other directly (i.e. code design patterns like 'module A <--> module B <--> module N <--> module A', will create huge mess when your program scales-up, so accessing in V shape i.e. through a separate manager module designed for managing such N modules. 'V'-shape is good any other shape is not that good (triangle, square or pentagon) in order to avoid weird unexpected "surprises" :)
Note 2: if you wish to control your program visibility in more granular detail & keep relative imports within your software,(at least in theory) you can abstract your program into layers with namespaces, in order to group your custom modules and manage their visibility in more exact manner:
Add namespace_folder(s) under your package root & divide your modules into the namespaces your want.
In package root's __init__.py
import only the namespaces (in similar manner as above) that you wish to offer visibility here between each other.
Now in each namespace, add each namespace __init__.py
, that list those modules you wish to allow visibility between and offer support for relative paths, while accessing each other.
So package provides/restricts visibility to N namespaces, namespaces provide/restrict visibility between & to their modules x,y,z with __init__.py
files defined.
^^ Note, if you define on package level __init__().py
so that your modules a,b,c can see each other (into global namespace) and then you have folder that groups modules d,e,f so that they form non-global namespace, lets say a_2.
Now if on this group parent folder you add __init__().py
and include d,e,f modules to it in order to provide relative imports from these modules to the global namespace classes and also to their shared non-global namespace's module-n's children-classes (that are located in module's local hierarchy-tree in N-depth) --> Python actually does sh** on itself in errors with the latter one big time. It seemed to be that one cannot import from module n-1's child class module n's child class relatively to the namespace defined.
Might be that I am missing something, but Python seem to work on this particular use-case entirely differently than any OOP-languages I been using before (like C# for instance), which might connect to the fact Python has no real code encapsulation (private/public class/functional level etc...). Correct if I am wrong, I had no time to observe more deeper Python's interesting design philosophy.
Upvotes: -1
Reputation: 1500
I had the same problem and after struggling I've solved it by using the below code:
%run fileName.ipynb
Upvotes: -3
Reputation: 197
Here is a three-liner for those who disagree with Guido:
import sys
from pathlib import Path
sys.path.append(str(Path(sys.argv[0]).absolute().parent.parent))
Hope it helps.
UPDATE: Discovered that this fails when the executable is called by a relative path. The solution is to use resolve()
instead of absolute()
:
import sys
from pathlib import Path
sys.path.append(str(Path(sys.argv[0]).resolve().parent.parent))
Upvotes: 10
Reputation: 42060
unfortunately, this module needs to be inside the package, and it also needs to be runnable as a script, sometimes. Any idea how I could achieve that?
It's quite common to have a layout like this...
main.py
mypackage/
__init__.py
mymodule.py
myothermodule.py
...with a mymodule.py
like this...
#!/usr/bin/env python3
# Exported function
def as_int(a):
return int(a)
# Test function for module
def _test():
assert as_int('1') == 1
if __name__ == '__main__':
_test()
...a myothermodule.py
like this...
#!/usr/bin/env python3
from .mymodule import as_int
# Exported function
def add(a, b):
return as_int(a) + as_int(b)
# Test function for module
def _test():
assert add('1', '1') == 2
if __name__ == '__main__':
_test()
...and a main.py
like this...
#!/usr/bin/env python3
from mypackage.myothermodule import add
def main():
print(add('1', '1'))
if __name__ == '__main__':
main()
...which works fine when you run main.py
or mypackage/mymodule.py
, but fails with mypackage/myothermodule.py
, due to the relative import...
from .mymodule import as_int
The way you're supposed to run it is by using the -m option and giving the path in the Python module system (rather than in the filesystem)...
python3 -m mypackage.myothermodule
...but it's somewhat verbose, and doesn't mix well with a shebang line like #!/usr/bin/env python3
.
An alternative is to avoid using relative imports, and just use...
from mypackage.mymodule import as_int
Either way, you'll need to run from the parent of mypackage
, or add that directory to PYTHONPATH
(either one will ensure that mypackage
is in the sys.path module search path). Or, if you want it to work "out of the box", you can frob the PYTHONPATH
in code first with this...
import sys
import os
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(SCRIPT_DIR))
from mypackage.mymodule import as_int
It's kind of a pain, but there's a clue as to why in an email written by a certain Guido van Rossum...
I'm -1 on this and on any other proposed twiddlings of the
__main__
machinery. The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern. To make me change my mind you'd have to convince me that it isn't.
Whether running scripts inside a package is an antipattern or not is subjective, but personally I find it really useful in a package I have which contains some custom wxPython widgets, so I can run the script for any of the source files to display a wx.Frame
containing only that widget for testing purposes.
Upvotes: 1398
Reputation: 25170
If the following import:
from . import something
doesn't work for you it is because this is python-packaging import and will not work with your regular implementation, and here is an example to show how to use it:
Folder structure:
.
└── funniest
├── funniest
│ ├── __init__.py
│ └── text.py
├── main.py
└── setup.py
inside __init__.py
add:
def available_module():
return "hello world"
text.py
add:
from . import available_module
inside setup.py
add
from setuptools import setup
setup(name='funniest',
version='0.1',
description='The funniest joke in the world',
url='http://github.com/storborg/funniest',
author='Flying Circus',
author_email='[email protected]',
license='MIT',
packages=['funniest'],
zip_safe=False)
Now, this is the most important part you need to install your package:
pip install .
Anywhere else in our system using the same Python, we can do this now:
>> import funnies.text as fun
>> fun.available_module()
This should output 'hello world'
you can test this in main.py
(this will not require any installation of the Package)
Here is main.py
as well
import funniest.text as fun
print(fun.available_module())
Upvotes: -1
Reputation: 173
I was getting the same error and my project structure was like
->project
->vendors
->vendors.py
->main.py
I was trying to call like this
from .vendors.Amazon import Amazom_Purchase
Here it was throwing an error so I fixed it simply by removing the first . from the statement
from vendors.Amazon import Amazom_Purchase
Hope this helps.
Upvotes: 2
Reputation: 3268
TL;DR
You can only relatively import modules inside another module in the same package.
Concept Clarify
We see a lot of example code in books/docs/articles, they show us how to relatively import a module, but when we do so, it fails.
The reason is, put it in a simple sentence, we did not run the code as the python module mechanism expects, even though the code is written totally right. It's like some kind of runtime thing.
Module loading is depended on how you run the code. That is the source of confusion.
What is a module?
A module is a python file when and only when it is being imported by another file. Given a file mod.py
, is it a module? Yes and No, if you run python mod.py
, it is not a module, because it is not imported.
What is a package?
A package is a folder that includes Python module(s).
BTW, __init__.py
is not necessary from python 3.3, if you don't need any package initialization or auto-load submodules. You don't need to place a blank __init__.py
in a directory.
That proves a package is just a folder as long as there are files being imported.
Real Answer
Now, this description becomes clearer.
You can only relatively import modules inside another module in the same package.
Given a directory:
. CWD
|-- happy_maker.py # content: print('Sends Happy')
`-- me.py # content: from . import happy_maker
Run python me.py
, we got attempted relative import with no known parent package
me.py
is run directly, it is not a module, and we can't use relative import in it.
Solution 1
Use import happy_maker
instead of from . import happy_maker
Solution 2
Switch our working directory to the parent folder.
. CWD
|-- happy
| |-- happy_maker.py
`-- me.py
Run python -m happy.me
.
When we are in the directory that includes happy
, happy
is a package, me.py, happy_maker.py
are modules, we can use relative import now, and we still want to run me.py
, so we use -m
which means run the module as a script.
Python Idiom
. CWD
|-- happy
| |-- happy_maker.py # content: print('Sends Happy')
| `-- me.py # content: from . import happy_maker
`-- main.py # content: import happy.me
This structure is the python idiom. main
is our script, best practice in Python. Finally, we got there.
Siblings or Grandparents
Another common need:
.
|-- happy
| |-- happy_maker.py
| `-- me.py
`-- sad
`-- sad_maker.py
We want to import sad_maker
in me.py
, How to do that?
First, we need to make happy
and sad
in the same package, so we have to go up a directory level. And then from ..sad import sad_maker
in the me.py
.
That is all.
Upvotes: 54
Reputation: 123
I think the best solution is to create a package for your module: Here is more info on how to do it.
Once you have a package you don't need to worry about relative import, you can just do absolute imports.
Upvotes: 3
Reputation: 574
Moving the file from which you are importing to an outside directory helps.
This is extra useful when your main file makes any other files in its own directory.
Ex:
Before:
Project
|---dir1
|-------main.py
|-------module1.py
After:
Project
|---module1.py
|---dir1
|-------main.py
Upvotes: 0
Reputation: 665
I ran into a similar problem when trying to write a python file that can be loaded either as a module or an executable script.
/path/to/project/
├── __init__.py
└── main.py
└── mylib/
├── list_util.py
└── args_util.py
with:
main.py:
#!/usr/bin/env python3
import sys
import mylib.args_util
if __name__ == '__main__':
print(f'{mylib.args_util.parseargs(sys.argv[1:])=}')
mylib/list_util.py:
def to_int_list(args):
return [int(x) for x in args]
mylib/args_util.py:
#!/usr/bin/env python3
import sys
from . import list_util as lu
def parseargs(args):
return sum(lu.to_int_list(args))
if __name__ == '__main__':
print(f'{parseargs(sys.argv[1:])=}')
$ ./main.py 1 2 3
mylib.args_util.parseargs(sys.argv[1:])=6
$ mylib/args_util.py 1 2 3
Traceback (most recent call last):
File "/path/to/project/mylib/args_util.py", line 10, in <module>
from . import list_util as lu
ImportError: attempted relative import with no known parent package
I settled for a Bash/Python polyglot solution. The Bash version of the program just calls python3 -m mylib.args_util
then exits.
The Python version ignores the Bash code because it's contained in the docstring.
The Bash version ignores the Python code because it uses exec
to stop parsing/running lines.
mylib/args_util.py:
#!/bin/bash
# -*- Mode: python -*-
''''true
exec /usr/bin/env python3 -m mylib.args_util "$@"
'''
import sys
from . import list_util as lu
def parseargs(args):
return sum(lu.to_int_list(args))
if __name__ == '__main__':
print(f'{parseargs(sys.argv[1:])=}')
$ ./main.py 1 2 3
mylib.args_util.parseargs(sys.argv[1:])=6
$ mylib/args_util.py 1 2 3
parseargs(sys.argv[1:])=6
#!/bin/bash
; this is the "shebang" line; it tells the interactive shell how run this script.
# -*- Mode: python -*-
optional; this is called the "mode-line"; it tells Emacs to use Python syntax highlighting instead of guessing that the language is Bash when reading the file.
''''true
'true\n
true
(i.e. '' + '' + 'true' = 'true'
); it then runs true
(which does nothing) and continues to the next lineexec /usr/bin/env python3 -m mylib.args_util "$@"
python3 -m mylib.args_util
then exits (it doesn't parse anything beyond this line)'''
python -m mylib.args_util
./path/to/project/
.
PYTHONPATH
when calling /usr/bin/env
#!/bin/bash
# -*- Mode: python -*-
''''true
exec /usr/bin/env python3 \
PYTHONPATH="$(cd "$(dirname "$0")/.." ; pwd)" \
-m mylib.args_util "$@"
'''
Upvotes: 1
Reputation: 21
The below solution is tested on Python3
├── classes
| |
| ├──__init__.py
| |
│ ├── userclass.py
| | |
| | └--viewDetails()
| |
| |
│ └── groupclass.py
| |
| └--viewGroupDetails()
|
└── start.py
└~~ uses function1()
Now, in order to use viewDetails of userclass or viewGroupDetails of groupclass define that in _ init _.py of classess directory first.
Ex: In _ init _.py
from .userclasss import viewDetails
from .groupclass import viewGroupDetails
Step2: Now, in start.py we can directly import viewDetails
Ex: In start.py
from classes import viewDetails
from classes import viewGroupDetails
Upvotes: 1
Reputation: 1185
Firstly, you can import from the same directory.
Here is the file structure...
Folder
|
├─ Scripts
| ├─ module123.py
|
├─ main.py
├─ script123.py
Here is main.py
from . import script123
from Scripts import module123
As you can see, importing from .
imports from current directory.
Note: if running using anything but IDLE, make sure that your terminal is navigated to the same directory as the
main.py
file before running.
Also, importing from a local folder also works.
As seen in my GitHub gist here, there is the following method.
Take the following file tree...
ParentDirectory
├─ Folder
| |
| ├─ Scripts
| | ├─ module123.py
| |
| ├─ main.py
| ├─ script123.py
|
├─ parentModule.py
Then, just add this code to the top of your main.py
file.
import inspect
import os
import sys
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(current_dir)
sys.path.insert(0, parent_dir)
from ParentDirectory import Stuff
Upvotes: 10
Reputation: 1124248
SystemError: Parent module '' not loaded, cannot perform relative import
This means you are running a module inside the package as a script. Mixing scripts inside packages is tricky and should be avoided if at all possible. Use a wrapper script that imports the package and runs your scripty
function instead.
If your top-level directory is called foo
, which is on your PYTHONPATH
module search path, and you have a package bar
there (it is a directory you'd expect an __init__.py
file in), scripts should not be placed inside bar
, but should live on in foo
at best.
Note that scripts differ from modules here in that they are used as a filename argument to the python
command, either by using python <filename>
or via a #!
(shebang) line. It is loaded directly as the __main__
module (this is why if __name__ == "__main__":
works in scripts), and there is no package context to build on for relative imports.
If you can, package your project with setuptools
(or poetry
or flit
, which can help simplify packaging), and create console script entrypoints; installing your project with pip
then creates scripts that know how to import your package properly. You can install your package locally with pip install -e .
, so it can still be edited in-place.
Otherwise, never, ever, use python path/to/packagename/file.py
, always use python path/to/script.py
and script.py
can use from packagename import ...
.
As a fallback, you could use the -m
command-line switch to tell Python to import a module and use that as the __main__
file instead. This does not work with a shebang line, as there is no script file any more, however.
If you use python -m foo.bar
and foo/bar.py
is found in a sys.path
directory, that is then imported and executed as __main__
with the right package context. If bar
is also a package, inside foo/
, it must have a __main__.py
file (so foo/bar/__main__.py
as the path from the sys.path
directory).
In extreme circumstances, add the metadata Python uses to resolve relative imports by setting __package__
directly; the file foo/bar/spam.py
, importable as foo.bar.spam
, is given the global __package__ = "foo.bar"
. It is just another global, like __file__
and __name__
, set by Python when imported.
sys.path
The above all requires that your package can be imported, which means it needs to be found in one of the directories (or zipfiles) listed in sys.path
. There are several options here too:
The directory where path/to/script.py
was found (so path/to
) is automatically added to sys.path
. Executing python path/to/foo.py
adds path/to
to sys.path
.
If you packaged your project (with setuptools
, poetry
, flit
or another Python packaging tool), and installed it, the package has been added to the right place already.
As a last resort, add the right directory to sys.path
yourself. If the package can be located relatively to the script file, use the __file__
variable in the script global namespace (e.g. using the pathlib.Path
object, HERE = Path(__file__).resolve().parent
is a reference to the directory the file lives in, as absolute path).
Upvotes: 52
Reputation: 4178
pathlib
library, and working for Jupyter notebooks where __file__
is not defined:You want to import my_function
defined under ../my_Folder_where_the_package_lives/my_package.py
respect to where you are writing the code.
Then do:
import os
import sys
import pathlib
PACKAGE_PARENT = pathlib.Path(__file__).parent
#PACKAGE_PARENT = pathlib.Path.cwd().parent # if on jupyter notebook
SCRIPT_DIR = PACKAGE_PARENT / "my_Folder_where_the_package_lives"
sys.path.append(str(SCRIPT_DIR))
from my_package import my_function
Upvotes: 16
Reputation: 21
This my project structure
├── folder
| |
│ ├── moduleA.py
| | |
| | └--function1()
| | └~~ uses function2()
| |
│ └── moduleB.py
| |
| └--function2()
|
└── main.py
└~~ uses function1()
Here my moduleA
imports moduleB
and main
imports moduleA
I added the snippet below in moduleA
to import moduleB
try:
from .moduleB import function2
except:
from moduleB import function2
Now I can execute both main.py
as well as moduleA.py
individually
Is this a solution ?
Upvotes: 2
Reputation: 3555
I encounter this a lot when I am working with Django, since a lot of functionality is performed from the manage.py
script but I also want to have some of my modules runnable directly as scripts as well (ideally you would make them manage.py
directives but we're not there yet).
This is a mock up of what such a project might look like;
├── dj_app
│ ├── models.py
│ ├── ops
│ │ ├── bar.py
│ │ └── foo.py
│ ├── script.py
│ ├── tests.py
│ ├── utils.py
│ └── views.py
└── manage.py
The important parts here being manage.py
, dj_app/script.py
, and dj_app/tests.py
. We also have submodules dj_app/ops/bar.py
and dj_app/ops/foo.py
which contain more items we want to use throughout the project.
The source of the issue commonly comes from wanting your dj_app/script.py
script methods to have test cases in dj_app/tests.py
which get invoked when you run manage.py test
.
This is how I set up the project and its import
s;
# dj_app/ops/foo.py
# Foo operation methods and classes
foo_val = "foo123"
.
# dj_app/ops/bar.py
# Bar operations methods and classes
bar_val = "bar123"
.
# dj_app/script.py
# script to run app methods from CLI
# if run directly from command line
if __name__ == '__main__':
from ops.bar import bar_val
from ops.foo import foo_val
# otherwise
else:
from .ops.bar import bar_val
from .ops.foo import foo_val
def script_method1():
print("this is script_method1")
print("bar_val: {}".format(bar_val))
print("foo_val: {}".format(foo_val))
if __name__ == '__main__':
print("running from the script")
script_method1()
.
# dj_app/tests.py
# test cases for the app
# do not run this directly from CLI or the imports will break
from .script import script_method1
from .ops.bar import bar_val
from .ops.foo import foo_val
def main():
print("Running the test case")
print("testing script method")
script_method1()
if __name__ == '__main__':
print("running tests from command line")
main()
.
# manage.py
# just run the test cases for this example
import dj_app.tests
dj_app.tests.main()
.
Running the test cases from manage.py
;
$ python3 manage.py
Running the test case
testing script method
this is script_method1
bar_val: bar123
foo_val: foo123
Running the script on its own;
$ python3 dj_app/script.py
running from the script
this is script_method1
bar_val: bar123
foo_val: foo123
Note that you get an error if you try to run the test.py
directly however, so don't do that;
$ python3 dj_app/tests.py
Traceback (most recent call last):
File "dj_app/tests.py", line 5, in <module>
from .script import script_method1
ModuleNotFoundError: No module named '__main__.script'; '__main__' is not a package
If I run into more complicated situations for imports, I usually end up implementing something like this to hack through it;
import os
import sys
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, THIS_DIR)
from script import script_method1
sys.path.pop(0)
Upvotes: 2
Reputation: 5933
My boilerplate to make a module
with relative imports in a package
runnable standalone.
package/module.py
## Standalone boilerplate before relative imports
if __package__ is None:
DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(DIR.parent))
__package__ = DIR.name
from . import variable_in__init__py
from . import other_module_in_package
...
Now you can use your module in any fashion:
python -m package.module
python -c 'from package import module'
python package/module.py
#!/bin/env python
) just: package/module.py
NB! Using sys.path.append
instead of sys.path.insert
will give you a hard to trace error if your module
has the same name as your package
. E.g. my_script/my_script.py
Of course if you have relative imports from higher levels in your package hierarchy, than this is not enough, but for most cases, it's just okay.
Upvotes: 13
Reputation: 470
I tried all of the above to no avail, only to realize I mistakenly had a -
in my package name.
In short, don't have -
in the directory where __init__.py
is. I've never felt elated after finding out such inanity.
Upvotes: 6
Reputation: 45140
TLDR; Append Script path to the System Path by adding following in the entry point of your python script.
import os.path
import sys
PACKAGE_PARENT = '..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
Thats it now you can run your project in PyCharma as well as from Terminal!!
Upvotes: 0
Reputation: 169
If none of the above worked for you, you can specify the module explicitly.
Directory:
├── Project
│ ├── Dir
│ │ ├── __init__.py
│ │ ├── module.py
│ │ └── standalone.py
Solution:
#in standalone.py
from Project.Dir.module import ...
module - the module to be imported
Upvotes: 5
Reputation: 1783
For PyCharm users:
I also was getting ImportError: attempted relative import with no known parent package
because I was adding the .
notation to silence a PyCharm parsing error. PyCharm innaccurately reports not being able to find:
lib.thing import function
If you change it to:
.lib.thing import function
it silences the error but then you get the aforementioned ImportError: attempted relative import with no known parent package
. Just ignore PyCharm's parser. It's wrong and the code runs fine despite what it says.
Upvotes: 22
Reputation: 2415
I was getting this ImportError: attempted relative import with no known parent package
In my program I was using the file from current path for importing its function.
from .filename import function
Then I modified the current path (Dot) with package name. Which resolved my issue.
from package_name.filename import function
I hope the above answer helps you.
Upvotes: 9
Reputation: 51
I had a similar problem: I needed a Linux service and cgi plugin which use common constants to cooperate. The 'natural' way to do this is to place them in the init.py of the package, but I cannot start the cgi plugin with the -m parameter.
My final solution was similar to Solution #2 above:
import sys
import pathlib as p
import importlib
pp = p.Path(sys.argv[0])
pack = pp.resolve().parent
pkg = importlib.import_module('__init__', package=str(pack))
The disadvantage is that you must prefix the constants (or common functions) with pkg:
print(pkg.Glob)
Upvotes: 0
Reputation: 139
I needed to run python3 from the main project directory to make it work.
For example, if the project has the following structure:
project_demo/
├── main.py
├── some_package/
│ ├── __init__.py
│ └── project_configs.py
└── test/
└── test_project_configs.py
I would run python3 inside folder project_demo/ and then perform a
from some_package import project_configs
Upvotes: 8
Reputation: 3354
Put this inside your package's __init__.py file:
# For relative imports to work in Python 3.6
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))
Assuming your package is like this:
├── project
│ ├── package
│ │ ├── __init__.py
│ │ ├── module1.py
│ │ └── module2.py
│ └── setup.py
Now use regular imports in you package, like:
# in module2.py
from module1 import class1
This works in both python 2 and 3.
Upvotes: 312