I have a module 'hydro' with the structure:
hydro/
__init__.py
read.py
write.py
hydro_main.py
This gets used as a submodule for several other modules, which have scripts with similar names:
scenarios/
__init__.py
read.py
write.py
scenarios_main.py
hydro/
__init__.py
read.py
write.py
hydro_main.py
In order to keep the script names straight, I want to specify the module name on import. So in the header of hydro_main.py, I'd have:
import hydro.read
and in scenarios_main.py, I'd have:
import hydro.read as read_hydro
import scenarios.read as read_scenarios
The problem is that when I attempt to run hydro_main.py from the package root, I get the following error:
ModuleNotFoundError: No module named 'hydro'
How can I set the package name for 'hydro' such that it will allow me to refer to the package name on import? I thought adding __init__.py was supposed to initialize the package, but __package__ still comes back as None.
You can import just the entire module as one instance.
import hydro
from hydro import read as read_hydro, hydro_main as main
hydro.hydro_main()
main() # same as above
hydro.read()
read_hydro() #same as above
It is a sub module so you have to use parentModule.subModule.* . Your first line will change to import scenarios.hydro.read as read_hydro
scenarios/hydro/hydro_main.py
print("I am in hydro_main")
scenarios/hydro/read.py
print("I am in hydro read")
scenarios/hydro/write.py
print("I am in hydro write")
scenarios/read.py
print("I am in scenarios read")
scenarios/write.py
print("I am in scenarios write")
scenarios/scenarios_main.py
import scenarios.hydro.read as read_hydro
import scenarios.read as read_scenarios
I am in hydro read
I am in scenarios read
Related
I have the following Python package with 2 moludes:
-pack1
|-__init__
|-mod1.py
|-mod2.py
-import_test.py
with the code:
# in mod1.py
a = 1
and
# in mod2.py
from mod1 import a
b = 2
and the __init__ code:
# in __init__.py
__all__ = ['mod1', 'mod2']
Next, I am trying to import the package:
# in import_test.py
from pack1 import *
But I get an error:
ModuleNotFoundError: No module named 'mod1'
If I remove the dependency "from mod1 import a" in mod2.py, the import goes correctly. But that dependency makes the import incorrect with that exception "ModuleNotFoundError".
???
The issue here is that from mod2 perspective the first level in which it will search for a module is in the path from which you are importing it (here I am assuming that pack1 is not in your PYTHONPATH and that you are importing it from the same directory where pack1 is contained).
This means that if pack1 is in the directory /dir/to/pack1 and you do:
from mod1 import a
Python will look for mod1 in the same directory as pack1, i.e., /dir/to/pack1.
To solve your issue it is enough to do either:
from pack1.mod1 import a
or in Python 3.5+
from .mod1 import a
As a side note, unless this is a must for you, I do not recommend designing your package to be used as from pack import *, even if __all__ exists to give you better control of your public API.
I have a project structure that looks like:
The file greet.py is given as:
def greet_morning(message):
print("Hello, {}", message)
def greet_evening(message):
print("Evening message: {}", message)
and the file msg.py is given as :
import sys
import os
sys.path.append(os.getcwd())
from greet.greet import greet_morning
greet_morning("heyy")
When I try to run msg.py as python message/msg.py, I get an error saying ImportError: No module named greet.greet. I am running this file from the root. Why do I get this error, when I have already added the cwd in the system path?
I think is
from untitled.greet.greet import greet_morning
if still doesnt work, add:
import sys
sys.path.append('../')
edit
I think you may find all the possible solutions here Importing files from different folder
add __init__.py inside greet and msg folder__init__.py
You have missed the file __init__.py in your module.
Just create an empty file __init__.py in greet folder.
There are several modules under different packages, shown below:
proj
tc_mgr_folder
tcd.py
package1/
__init__.py
subPack1/
__init__.py
module_11.py
module_12.py
module_13.py
subPack2/
__init__.py
module_21.py
module_22.py
...
I would like to write a loop includes those modules(module_11, module_12, module_13, module_21, module_22,...) in tcd.py to test all once. Then save the output messages exported from each module to a text file. Can I do it?
You can get the files in a directory using glob.glob.
You can then import each module using importlib.import_module:
for module in ['os', 'sys']:
try:
importlib.import_module(module)
except ImportError:
print("Could not import module: {}".format(module))
I have created my own module with filename mymodule.py. The file contains:
def testmod():
print "test module success"
I have placed this file within /Library/Python/2.7/site-packages/mymodule/mymodule.py
I have also added a __init__.py file, these have compiled to generate
__init__.pyc and mymodule.pyc
Then in the python console I import it
import mymodule
which works fine
when I try to use mymodule.testmod() I get the following error:
AttributeError: 'module' object has no attribute 'testmod'
So yeah it seems like it has no functions?
You have a package mymodule, containing a module mymodule. The function is part of the module, not the package.
Import the module:
import mymodule.mymodule
and reference the function on that:
mymodule.mymodule.testmod()
You can use from ... import and import ... as to influence what gets imported exactly:
from mymodule import mymodule
mymodule.testmod()
or
from mymodule import mymodule as nestedmodule
nestedmodule.testmod
or
from mymodule.mymodule import testmod
testmod()
etc.
I have a module called spellnum. It can be used as a command-line utility (it has the if __name__ == '__main__': block) or it can be imported like a standard Python module.
The module defines a class named Speller which looks like this:
class Speller(object):
def __init__(self, lang="en"):
module = __import__("spelling_" + lang)
# use module's contents...
As you can see, the class constructor loads other modules at runtime. Those modules (spelling_en.py, spelling_es.py, etc.) are located in the same directory as the spellnum.py itself.
Besides spellnum.py, there are other files with utility functions and classes. I'd like to hide those files since I don't want to expose them to the user and since it's a bad idea to pollute the Python's lib directory with random files. The only way to achieve this that I know of is to create a package.
I've come up with this layout for the project (inspired by this great tutorial):
spellnum/ # project root
spellnum/ # package root
__init__.py
spellnum.py
spelling_en.py
spelling_es.py
squash.py
# ... some other private files
test/
test_spellnum.py
example.py
The file __init__.py contains a single line:
from spellnum import Speller
Given this new layout, the code for dynamic module loading had to be changed:
class Speller(object):
def __init__(self, lang="en"):
spelling_mod = "spelling_" + lang
package = __import__("spellnum", fromlist=[spelling_mod])
module = getattr(package, spelling_mod)
# use module as usual
So, with this project layout a can do the following:
Successfully import spellnum inside example.py and use it like a simple module:
# an excerpt from the example.py file
import spellnum
speller = spellnum.Speller(es)
# ...
import spellnum in the tests and run those tests from the project root like this:
$ PYTHONPATH="`pwd`:$PYTHONPATH" python test/test_spellnum.py
The problem
I cannot execute spellnum.py directly with the new layout. When I try to, it shows the following error:
Traceback (most recent call last):
...
File "spellnum/spellnum.py", line 23, in __init__
module = getattr(package, spelling_mod)
AttributeError: 'module' object has no attribute 'spelling_en'
The question
What's the best way to organize all of the files required by my module to work so that users are able to use the module both from command line and from their Python code?
Thanks!
How about keeping spellnum.py?
spellnum.py
spelling/
__init__.py
en.py
es.py
Your problem is, that the package is called the same as the python-file you want to execute, thus importing
from spellnum import spellnum_en
will try to import from the file instead of the package. You could fiddle around with relative imports, but I don't know how to make them work with __import__, so I'd suggest the following:
def __init__(self, lang="en"):
mod = "spellnum_" + lang
module = None
if __name__ == '__main__':
module = __import__(mod)
else:
package = getattr(__import__("spellnum", fromlist=[mod]), mod)