Reputation: 19565
Very easy issue to replicate. My current setup is:
package/
__init__.py
run.py
In my __init.py__
I have:
blah = 4
And in my run.py
I have:
from package import blah
if __name__ == '__main__':
print(blah)
I simply run it with python run.py
. But I am getting ImportError: cannot import name 'blah'
.
How come I am not being able to import a variable from my package? I know how to workaround it, I am rather interested in knowing the reason for the error.
Upvotes: 4
Views: 5420
Reputation: 5359
You are clearly trying to execute this as a package, but you are running "run.py" as if it were a standard python script. run.py
does not have a concept of module
in the sense of how you are trying to run it. You need to re-architect your design here. in the package module
run.py
would be a module (these are your naming conventions here). So module
is the package, and run.py
is a module. You then need a __main__.py
to execute this as a package and you need to change your run.py:
run.py
:
#!/usr/bin/env python3
from module1 import blah
def run():
print(blah)
__main__.py
:
#!/usr/bin/env python3
from module1 import run
def main():
run.run() # run is the module name, and run is also the function name so we execute with run.run
main()
__init__.py
:
blah = 4
directory structure:
module1/
- __init__.py
- __main__.py
- run.py
to execute (outside of module1
):
[dkennetz@nodem103 fun]$ python3.5 -m module1
4
If you do not want to make this a package, you should simply create a directory called package
and inside you can make run.py
and variables.py
.
variables.py:
blah=4
blahblah=8
blahblahblah=12
run.py:
from variables import blah
print(blah)
prints 4
if you changed run.py to:
from variables import blah, blahblah
print(blah)
print(blahblah)
[dkennetz@nodem103 package]$ python3.5 run.py
4
8
Or you can import all variables by changing run.py to:
from variables import *
print(blah)
print(blahblah)
print(blahblahblah) # if this was added to variables.py as 12
It returns:
[dkennetz@nodem103 package]$ python3.5 run.py
4
8
12
Upvotes: 4
Reputation: 1265
In python, package and module are two different concept. module is single py file and package must be a dir which must contain __init__.py
.
__init__.py
is for packages
, when you run run.py in package dir, package dir can not be treated as a package
, and package dir of course are not module
. So it raised the error: ModuleNotFoundError: No module named xxxx
.
When a regular package is imported, this
__init__.py
file is implicitly executed, and the objects it defines are bound to names in the package’s namespace.
5. The import system — Python 3.7.4rc1 documentation
Upvotes: 0
Reputation: 4866
I'm assuming you are running python run.py
from within the directory package
. Python then looks for a package (a directory) or a module (.py
file) named "package" inside that directory, but neither exists. As it cannot import the symbol blah
, it raises an ImportError
.
Upvotes: 2
Reputation: 963
Your issue is that you are trying to import from the module you are in.
Here is my structure
[syspath]
$ tree
.
├── mod
│ ├── __init__.py
│ └── run.py
└── orun.py
1 directory, 3 files
[syspath]
$ cat mod/run.py
#from mod import blah
from . import blah
print(blah)
[syspath]
$ cat orun.py
from mod import blah
print(blah)
[syspath]
$ python3 orun.py
4
[syspath]
$ python3 -m mod.run
4
Being within the module
directory you are effectively a part of the module and can't import it, you can however reference it as a sibling but only if you are being run as a part of the module, as in python3 -m mod.run
the -m
is run this as a module.
A bit more of an understanding, python import
looks for entries available in sys.path
,
Here are the sys.path
s found in the orun.py
(outside of the module), and mod/run.py
within the module.
[syspath]
$ python3 orun.py
['~/syspath',
'/usr/lib/python37.zip',
'/usr/lib/python3.7',
'/usr/lib/python3.7/lib-dynload',
'~/.local/lib/python3.7/site-packages',
'/usr/local/lib/python3.7/dist-packages',
'/usr/lib/python3/dist-packages']
[syspath]
$ python3 mod/run.py
['~/syspath/mod',
'/usr/lib/python37.zip',
'/usr/lib/python3.7',
'/usr/lib/python3.7/lib-dynload',
'~/.local/lib/python3.7/site-packages',
'/usr/local/lib/python3.7/dist-packages',
'/usr/lib/python3/dist-packages']
As you see when you are inside of mod
you can't find another mod inside of it.
Try adding a new file in the directory with the same name module.py
and put a different value for blah
and you will see the code execute with that value.
[syspath]
$ tree
.
├── mod
│ ├── __init__.py
│ ├── mod.py
│ └── run.py
└── orun.py
1 directory, 4 files
[syspath]
$ cat mod/mod.py
blah = 40
[syspath]
$ python3 mod/run.py
40
Upvotes: 1