Python - import module which imports module - python

I have three scripts in the same location:
/__init__.py
interface.py
radio.py
playlist.py
playlist.py has child classes stored, like:
class playlist1(radio):
'''child class'''
and radio.py has the parent class:
class radio(object):
'''parent class'''
I'm trying to run interface.py, which has:
if __name__ == "__main__":
from playlist import *
in playlist.py I have this import, on its turn:
from radio import radio
but when I run interface.py, I get the following error:
ImportError: cannot import name radio
I use python 2.x. what's wrong?

Your description of the situation has omitted a crucial part: the package where these modules live. For example, if they live in the foo package, the situation would look like this:
foo/
__init__.py
interface.py
radio.py
playlist.py
In that context, there are two common ways for the playlist module to import names from the radio module:
# 1. Fully qualified.
from foo.radio import radio
# 2. Relative import.
from .radio import radio
The second approach is strongly recommended because it leaves no room for ambiguity.
You also haven't told us how you are running interface.py. Those details can affect the importing situation as well.
If you are organizing code in packages, you need to follow a conventional
project structure. In this layout, you would tend to work in the project
root. Also you need a proper setup.py file. Here's what it might look like:
# ----
# Directory layout.
some_project/
foo/
__init__.py
interface.py
playlist.py
radio.py
setup.py
# You work at this level.
# ----
# interface.py
from playlist import radio
def main():
print radio
# ----
# playlist.py
from .radio import radio
# ----
# radio.py
radio = 123
# ----
# setup.py
from setuptools import setup
setup(
name = 'foo',
version = '1.0',
zip_safe = False,
packages = ['foo'],
entry_points = {
'console_scripts': [
'foobar = foo.interface:main',
],
},
)
# ----
# Install stuff for dev work (ie in "editable" mode).
pip install -e .
# ----
# Run the command line entry point.
foobar

I think you just need to make an empty file called
__init__.py
in the same directory as the files. That will let Python2 knows that it's okay to import from this directory.
Then use your code.

Related

import error when importing module from the same directory [duplicate]

I have a directory that stores all the .py files.
bin/
main.py
user.py # where class User resides
dir.py # where class Dir resides
I want to use classes from user.py and dir.py in main.py.
How can I import these Python classes into main.py?
Furthermore, how can I import class User if user.py is in a sub directory?
bin/
dir.py
main.py
usr/
user.py
Python 2
Make an empty file called __init__.py in the same directory as the files. That will signify to Python that it's "ok to import from this directory".
Then just do...
from user import User
from dir import Dir
The same holds true if the files are in a subdirectory - put an __init__.py in the subdirectory as well, and then use regular import statements, with dot notation. For each level of directory, you need to add to the import path.
bin/
main.py
classes/
user.py
dir.py
So if the directory was named "classes", then you'd do this:
from classes.user import User
from classes.dir import Dir
Python 3
Same as previous, but prefix the module name with a . if not using a subdirectory:
from .user import User
from .dir import Dir
I just learned (thanks to martineau's comment) that, in order to import classes from files within the same directory, you would now write in Python 3:
from .user import User
from .dir import Dir
From python3.3 upwards, __init__.py is no longer necessary. If the current directory of the console is the directory where the python script is located, everything works fine with
import user
However, this won't work if called from a different directory, which does not contain user.py.
In that case, use
from . import user
This works even if you want to import the whole file instead of just a class from there.
In your main.py:
from user import Class
where Class is the name of the class you want to import.
If you want to call a method of Class, you can call it using:
Class.method
Note that there should be an empty __init__.py file in the same directory.
If user.py and dir.py are not including classes then
from .user import User
from .dir import Dir
is not working. You should then import as
from . import user
from . import dir
You can import the module and have access through its name if you don't want to mix functions and classes with yours
import util # imports util.py
util.clean()
util.setup(4)
or you can import the functions and classes to your code
from util import clean, setup
clean()
setup(4)
you can use wildchar * to import everything in that module to your code
from util import *
clean()
setup(4)
To make it more simple to understand:
Step 1: lets go to one directory, where all will be included
$ cd /var/tmp
Step 2: now lets make a class1.py file which has a class name Class1 with some code
$ cat > class1.py <<\EOF
class Class1:
OKBLUE = '\033[94m'
ENDC = '\033[0m'
OK = OKBLUE + "[Class1 OK]: " + ENDC
EOF
Step 3: now lets make a class2.py file which has a class name Class2 with some code
$ cat > class2.py <<\EOF
class Class2:
OKBLUE = '\033[94m'
ENDC = '\033[0m'
OK = OKBLUE + "[Class2 OK]: " + ENDC
EOF
Step 4: now lets make one main.py which will be execute once to use Class1 and Class2 from 2 different files
$ cat > main.py <<\EOF
"""this is how we are actually calling class1.py and from that file loading Class1"""
from class1 import Class1
"""this is how we are actually calling class2.py and from that file loading Class2"""
from class2 import Class2
print Class1.OK
print Class2.OK
EOF
Step 5: Run the program
$ python main.py
The output would be
[Class1 OK]:
[Class2 OK]:
Python 3
Same directory.
import file:log.py
import class: SampleApp().
import log
if __name__ == "__main__":
app = log.SampleApp()
app.mainloop()
or
directory is basic.
import in file: log.py.
import class: SampleApp().
from basic import log
if __name__ == "__main__":
app = log.SampleApp()
app.mainloop()
from user import User
from dir import Dir
For Python 3+, suppose you have this structure:
A/
__init__.py
bar.py
foo.py
In your __init__.py file, you can put from . import foo
then you can import foo in bar file
# A/bar.py
from foo import YourClass
The purpose of the __init__.py files is to include optional initialization code that runs as different levels of a package are encountered. everything you put in the __init__.py will be initialized during the package load.
I'm not sure why this work but using Pycharm build from file_in_same_dir import class_name
The IDE complained about it but it seems it still worked. I'm using Python 3.7
For python3
import from sibling: from .user import User
import from nephew: from .usr.user import User
If you have filename.py in the same folder, you can easily import it like this:
import filename
I am using python3.7
Python3
use
from .user import User inside dir.py file
and
use from class.dir import Dir inside main.py
or from class.usr import User inside main.py
like so
# My Python version: 3.7
# IDE: Pycharm 2021.1.2 Community
# Have "myLib" in folder "labs":
class Points:
def __init__(self, x = 0, y = 0):
self.__x = x
self.__y = y
def __str__(self):
return f"x = {self.__x}, y = {self.__y}"
# Have "myFile" in (same) folder "labs":
from myFile import Point
p1 = Point(1, 4)
p2 = Point(1, 4)
print(f"p1: {p1}, p2: {p2}")
# Result:
# p1: x = 1, y = 4, p2: x = 1, y = 4
# Good Luck!
Indeed Python does not provide an elegant solution for this everyday use-case. It is especially problematic when you are testing your code that eventually will be delivered as part of a Python package. Here is an approach that has worked for me:
dir
|
file1.py
file2.py
And let's say you want to import file2 from file1.
# In file1.py:
try:
# This works when packaged as Python package
from . import file2
except:
# This works when simply invoking file1 as a module (i.e. python file1)
import file2
# rest of the code ...
I cannot submit an edit for the top answer, so based on some pointers given in comments above, another thing to try out is:
from subfolder.MyClassFile import MyClass
And that's it. Just remember to have an __init__.py empty file in our subfolder.
Just for reference, the solution works if your structure is something like this:
your_project/
__ini__.py
main.py
subfolder/
__init__.py
MyClassFile.py <-- You want this
MyClassFile.py contains the class MyClass.
Just too brief,
Create a file __init__.py is classes directory and then import it to your script like following (Import all case)
from classes.myscript import *
Import selected classes only
from classes.myscript import User
from classes.myscript import Dir
to import from the same directory
from . import the_file_you_want_to_import
to import from sub directory the directory should contain
init.py
file other than you files then
from directory import your_file

A strange "No module named 'XX' " problem

I know how to import a package or module, but I meet a quite strange problem.
If I run swmm5_extend_function/example.py, everything is fine. However, when I run example.py, errors occur:
Traceback (most recent call last):
File "example.py", line 2, in <module>
from swmm5_extend_function.Swmm5Extend import SWMM5ReadInp
File "C:\project\swmm5_extend_function\Swmm5Extend.py", line 1, in <module>
import swig.SWMM5ReadInpFile as swmm
ModuleNotFoundError: No module named 'swig'
Here is my project structure:
project/
-- example.py
-- ......
-- swmm5_extend_function/
-- __init__.py
-- example.py
-- Swmm5Extend.py
-- swig/
-- __init__.py
-- SWMM5ReadInpFile.py
-- ....
Here is code of each .py file:
swmm5_extend_function/Swmm5Extend.py
import swig.SWMM5ReadInpFile as swmm
class SWMM5ReadInp(object):
pass
swmm5_extend_function/example.py
from Swmm5Extend import SWMM5ReadInp
example.py
from swmm5_extend_function.Swmm5Extend import SWMM5ReadInp
I want to know why this strange error happens.
For a better explanation, I've created the following folder structure:
test/
-- __init__.py
-- greeter.py # Greets in German
-- subfolder/
-- __init__.py
-- greeter.py # Greets in Italian
-- test.py
-- deepfolder/
-- __init__.py
-- greeter.py # Greets in France
As you may notice, we have 3 files with the same name, each one greets in a different language using a function with the same name. The only function in a greeter.py file is:
def says():
print("Hello World!")
IMPORT FROM THE SAME FOLDER
If from test.py file we import greeter and run the says function, we'll have:
import greeter as greeter
greeter.says()
Output:
Buongiorno Mondo! # Italian output
IMPORT FROM A SUBFOLDER
But what if we want to import from a subfolder?
To import from a subfolder (i.e., deepfolder/), we simply add an empty __init__.py file into the folder, then we can specify the path in the import:
import deepfolder.greeter as greeter
greeter.says()
Output:
Bonjour le Monde! # France output
IMPORT FROM A PARENT FOLDER
At last, you may want to import from a parent folder.
You should try to have your main running file at the top of the folder tree, but things happens and you find yourself looking to import a module from a parent folder.
For doing this, you need to add the parent folder to the sys.path:
import sys
sys.path.append("/path/to/dir")
from test import greeter as greeter
greeter.says()
Output:
Guten Morgen Welt! # German output
Importing scripts and modules isn't really the most pythonic way to solve things, you may want to have a look on Python's documentation about packages.
TL;DR
In your project/example.py use
import swmm5_extend_function.swig.SWMM5ReadInpFile as swmm
instead of
import swig.SWMM5ReadInpFile as swmm

Package organisation in Python

I am having problems to manage my modules and pacakges dependencies in Python. I am in Windows 7 and using Python 3.3
I want to have a basic structrure like this:
/
myTask.py
-->utils
--> utils1.py
--> utils2.py
-->processes
--> process1.py
--> process2.py
MyTask will run process1. Process1 imports process2 and imports the utils1 and utils2 in the utils package
So in process1 I have
import sys
sys.path.append('..path..\\utils\\')
from utils1 import *
from utils2 import *
from process2 import *
if __name__ == '__main__':
my_method()
def my_method():
####CODE
I can run Process1 as script and works fine.
MyTask.py looks like:
import processes.process1
process1.my_method()
When I run it I recieve and error that says:
ImportError: No module named 'process2'
Is my package/module structure correct? Why do I receive that error?
There are several errors in the structure you have created.
First of all, in python package must contain __init__.py file at it's root. It's ordinary python file and it might be completely empty. It's required to mark folder as python package
Next, you shouldn't mess with sys.path excplicitly, especially using relative paths (unless you are sure what you are doing, but this time you definitely not).
So, the correct folder structure would be
/MyTask.py
/processes
__init__.py
process1.py
process2.py
/utils
__init__.py
utils1.py
utils2.py
And process1.py:
from utils import utils1, utils2 # relative import
import process2 # import from same package
# everything else
MyTask.py:
import processes.process1
process1.my_method()
More on packaging in python docs

How to run unittest discover from "python setup.py test"?

I'm trying to figure out how to get python setup.py test to run the equivalent of python -m unittest discover. I don't want to use a run_tests.py script and I don't want to use any external test tools (like nose or py.test). It's OK if the solution only works on python 2.7.
In setup.py, I think I need to add something to the test_suite and/or test_loader fields in config, but I can't seem to find a combination that works correctly:
config = {
'name': name,
'version': version,
'url': url,
'test_suite': '???',
'test_loader': '???',
}
Is this possible using only unittest built into python 2.7?
FYI, my project structure looks like this:
project/
package/
__init__.py
module.py
tests/
__init__.py
test_module.py
run_tests.py <- I want to delete this
setup.py
Update: This is possible with unittest2 but I want find something equivalent using only unittest
From https://pypi.python.org/pypi/unittest2
unittest2 includes a very basic setuptools compatible test collector. Specify test_suite = 'unittest2.collector' in your setup.py. This starts test discovery with the default parameters from the directory containing setup.py, so it is perhaps most useful as an example (see unittest2/collector.py).
For now, I'm just using a script called run_tests.py, but I'm hoping I can get rid of this by moving to a solution that only uses python setup.py test.
Here's the run_tests.py I'm hoping to remove:
import unittest
if __name__ == '__main__':
# use the default shared TestLoader instance
test_loader = unittest.defaultTestLoader
# use the basic test runner that outputs to sys.stderr
test_runner = unittest.TextTestRunner()
# automatically discover all tests in the current dir of the form test*.py
# NOTE: only works for python 2.7 and later
test_suite = test_loader.discover('.')
# run the test suite
test_runner.run(test_suite)
If you use py27+ or py32+, the solution is pretty simple:
test_suite="tests",
From Building and Distributing Packages with Setuptools (emphasis mine):
test_suite
A string naming a unittest.TestCase subclass (or a package or module
containing one or more of them, or a method of such a subclass), or naming
a function that can be called with no arguments and returns a unittest.TestSuite.
Hence, in setup.py you would add a function that returns a TestSuite:
import unittest
def my_test_suite():
test_loader = unittest.TestLoader()
test_suite = test_loader.discover('tests', pattern='test_*.py')
return test_suite
Then, you would specify the command setup as follows:
setup(
...
test_suite='setup.my_test_suite',
...
)
You don't need config to get this working. There are basically two main ways to do it:
The quick way
Rename your test_module.py to module_test.py (basically add _test as a suffix to tests for a particular module), and python will find it automatically. Just make sure to add this to setup.py:
from setuptools import setup, find_packages
setup(
...
test_suite = 'tests',
...
)
The long way
Here's how to do it with your current directory structure:
project/
package/
__init__.py
module.py
tests/
__init__.py
test_module.py
run_tests.py <- I want to delete this
setup.py
Under tests/__init__.py, you want to import the unittest and your unit test script test_module, and then create a function to run the tests. In tests/__init__.py, type in something like this:
import unittest
import test_module
def my_module_suite():
loader = unittest.TestLoader()
suite = loader.loadTestsFromModule(test_module)
return suite
The TestLoader class has other functions besides loadTestsFromModule. You can run dir(unittest.TestLoader) to see the other ones, but this one is the simplest to use.
Since your directory structure is such, you'll probably want the test_module to be able to import your module script. You might have already done this, but just in case you didn't, you could include the parent path so that you can import the package module and the module script. At the top of your test_module.py, type:
import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import unittest
import package.module
...
Then finally, in setup.py, include the tests module and run the command you created, my_module_suite:
from setuptools import setup, find_packages
setup(
...
test_suite = 'tests.my_module_suite',
...
)
Then you just run python setup.py test.
Here is a sample someone made as a reference.
One possible solution is to simply extend the test command for distutilsand setuptools/distribute. This seems like a total kluge and way more complicated than I would prefer, but seems to correctly discover and run all the tests in my package upon running python setup.py test. I'm holding off on selecting this as the answer to my question in hopes that someone will provide a more elegant solution :)
(Inspired by https://docs.pytest.org/en/latest/goodpractices.html#integrating-with-setuptools-python-setup-py-test-pytest-runner)
Example setup.py:
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
def discover_and_run_tests():
import os
import sys
import unittest
# get setup.py directory
setup_file = sys.modules['__main__'].__file__
setup_dir = os.path.abspath(os.path.dirname(setup_file))
# use the default shared TestLoader instance
test_loader = unittest.defaultTestLoader
# use the basic test runner that outputs to sys.stderr
test_runner = unittest.TextTestRunner()
# automatically discover all tests
# NOTE: only works for python 2.7 and later
test_suite = test_loader.discover(setup_dir)
# run the test suite
test_runner.run(test_suite)
try:
from setuptools.command.test import test
class DiscoverTest(test):
def finalize_options(self):
test.finalize_options(self)
self.test_args = []
self.test_suite = True
def run_tests(self):
discover_and_run_tests()
except ImportError:
from distutils.core import Command
class DiscoverTest(Command):
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
discover_and_run_tests()
config = {
'name': 'name',
'version': 'version',
'url': 'http://example.com',
'cmdclass': {'test': DiscoverTest},
}
setup(**config)
Another less than ideal solution slightly inspired by http://hg.python.org/unittest2/file/2b6411b9a838/unittest2/collector.py
Add a module that returns a TestSuite of discovered tests. Then configure setup to call that module.
project/
package/
__init__.py
module.py
tests/
__init__.py
test_module.py
discover_tests.py
setup.py
Here's discover_tests.py:
import os
import sys
import unittest
def additional_tests():
setup_file = sys.modules['__main__'].__file__
setup_dir = os.path.abspath(os.path.dirname(setup_file))
return unittest.defaultTestLoader.discover(setup_dir)
And here's setup.py:
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
config = {
'name': 'name',
'version': 'version',
'url': 'http://example.com',
'test_suite': 'discover_tests',
}
setup(**config)
Python's standard library unittest module supports discovery (in Python 2.7 and later, and Python 3.2 and later). If you can assume those minimum versions, then you can just add the discover command line argument to the unittest command.
Only a small tweak is needed to setup.py:
import setuptools.command.test
from setuptools import (find_packages, setup)
class TestCommand(setuptools.command.test.test):
""" Setuptools test command explicitly using test discovery. """
def _test_args(self):
yield 'discover'
for arg in super(TestCommand, self)._test_args():
yield arg
setup(
...
cmdclass={
'test': TestCommand,
},
)
This won't remove run_tests.py, but will make it work with setuptools. Add:
class Loader(unittest.TestLoader):
def loadTestsFromNames(self, names, _=None):
return self.discover(names[0])
Then in setup.py: (I assume you're doing something like setup(**config))
config = {
...
'test_loader': 'run_tests:Loader',
'test_suite': '.', # your start_dir for discover()
}
The only downside I see is it's bending the semantics of loadTestsFromNames, but the setuptools test command is the only consumer, and calls it in a specified way.

How to import the class within the same directory or sub directory?

I have a directory that stores all the .py files.
bin/
main.py
user.py # where class User resides
dir.py # where class Dir resides
I want to use classes from user.py and dir.py in main.py.
How can I import these Python classes into main.py?
Furthermore, how can I import class User if user.py is in a sub directory?
bin/
dir.py
main.py
usr/
user.py
Python 2
Make an empty file called __init__.py in the same directory as the files. That will signify to Python that it's "ok to import from this directory".
Then just do...
from user import User
from dir import Dir
The same holds true if the files are in a subdirectory - put an __init__.py in the subdirectory as well, and then use regular import statements, with dot notation. For each level of directory, you need to add to the import path.
bin/
main.py
classes/
user.py
dir.py
So if the directory was named "classes", then you'd do this:
from classes.user import User
from classes.dir import Dir
Python 3
Same as previous, but prefix the module name with a . if not using a subdirectory:
from .user import User
from .dir import Dir
I just learned (thanks to martineau's comment) that, in order to import classes from files within the same directory, you would now write in Python 3:
from .user import User
from .dir import Dir
From python3.3 upwards, __init__.py is no longer necessary. If the current directory of the console is the directory where the python script is located, everything works fine with
import user
However, this won't work if called from a different directory, which does not contain user.py.
In that case, use
from . import user
This works even if you want to import the whole file instead of just a class from there.
In your main.py:
from user import Class
where Class is the name of the class you want to import.
If you want to call a method of Class, you can call it using:
Class.method
Note that there should be an empty __init__.py file in the same directory.
If user.py and dir.py are not including classes then
from .user import User
from .dir import Dir
is not working. You should then import as
from . import user
from . import dir
You can import the module and have access through its name if you don't want to mix functions and classes with yours
import util # imports util.py
util.clean()
util.setup(4)
or you can import the functions and classes to your code
from util import clean, setup
clean()
setup(4)
you can use wildchar * to import everything in that module to your code
from util import *
clean()
setup(4)
To make it more simple to understand:
Step 1: lets go to one directory, where all will be included
$ cd /var/tmp
Step 2: now lets make a class1.py file which has a class name Class1 with some code
$ cat > class1.py <<\EOF
class Class1:
OKBLUE = '\033[94m'
ENDC = '\033[0m'
OK = OKBLUE + "[Class1 OK]: " + ENDC
EOF
Step 3: now lets make a class2.py file which has a class name Class2 with some code
$ cat > class2.py <<\EOF
class Class2:
OKBLUE = '\033[94m'
ENDC = '\033[0m'
OK = OKBLUE + "[Class2 OK]: " + ENDC
EOF
Step 4: now lets make one main.py which will be execute once to use Class1 and Class2 from 2 different files
$ cat > main.py <<\EOF
"""this is how we are actually calling class1.py and from that file loading Class1"""
from class1 import Class1
"""this is how we are actually calling class2.py and from that file loading Class2"""
from class2 import Class2
print Class1.OK
print Class2.OK
EOF
Step 5: Run the program
$ python main.py
The output would be
[Class1 OK]:
[Class2 OK]:
Python 3
Same directory.
import file:log.py
import class: SampleApp().
import log
if __name__ == "__main__":
app = log.SampleApp()
app.mainloop()
or
directory is basic.
import in file: log.py.
import class: SampleApp().
from basic import log
if __name__ == "__main__":
app = log.SampleApp()
app.mainloop()
from user import User
from dir import Dir
For Python 3+, suppose you have this structure:
A/
__init__.py
bar.py
foo.py
In your __init__.py file, you can put from . import foo
then you can import foo in bar file
# A/bar.py
from foo import YourClass
The purpose of the __init__.py files is to include optional initialization code that runs as different levels of a package are encountered. everything you put in the __init__.py will be initialized during the package load.
I'm not sure why this work but using Pycharm build from file_in_same_dir import class_name
The IDE complained about it but it seems it still worked. I'm using Python 3.7
For python3
import from sibling: from .user import User
import from nephew: from .usr.user import User
If you have filename.py in the same folder, you can easily import it like this:
import filename
I am using python3.7
Python3
use
from .user import User inside dir.py file
and
use from class.dir import Dir inside main.py
or from class.usr import User inside main.py
like so
# My Python version: 3.7
# IDE: Pycharm 2021.1.2 Community
# Have "myLib" in folder "labs":
class Points:
def __init__(self, x = 0, y = 0):
self.__x = x
self.__y = y
def __str__(self):
return f"x = {self.__x}, y = {self.__y}"
# Have "myFile" in (same) folder "labs":
from myFile import Point
p1 = Point(1, 4)
p2 = Point(1, 4)
print(f"p1: {p1}, p2: {p2}")
# Result:
# p1: x = 1, y = 4, p2: x = 1, y = 4
# Good Luck!
Indeed Python does not provide an elegant solution for this everyday use-case. It is especially problematic when you are testing your code that eventually will be delivered as part of a Python package. Here is an approach that has worked for me:
dir
|
file1.py
file2.py
And let's say you want to import file2 from file1.
# In file1.py:
try:
# This works when packaged as Python package
from . import file2
except:
# This works when simply invoking file1 as a module (i.e. python file1)
import file2
# rest of the code ...
I cannot submit an edit for the top answer, so based on some pointers given in comments above, another thing to try out is:
from subfolder.MyClassFile import MyClass
And that's it. Just remember to have an __init__.py empty file in our subfolder.
Just for reference, the solution works if your structure is something like this:
your_project/
__ini__.py
main.py
subfolder/
__init__.py
MyClassFile.py <-- You want this
MyClassFile.py contains the class MyClass.
Just too brief,
Create a file __init__.py is classes directory and then import it to your script like following (Import all case)
from classes.myscript import *
Import selected classes only
from classes.myscript import User
from classes.myscript import Dir
to import from the same directory
from . import the_file_you_want_to_import
to import from sub directory the directory should contain
init.py
file other than you files then
from directory import your_file

Categories

Resources