This question already has answers here:
Relative imports for the billionth time
(12 answers)
Closed 3 months ago.
I have a directory and module design that looks like this:
MyProject --- - script.py
|
- helpers --- - __init__.py
|
- class_container.py
|
- helper.py
# class_container.py
class MyClass:
pass
# helper.py
from class_container import MyClass
def func():
# some code using MyClass
# script.py
from helpers.helper import func
When I run script.py:
ModuleNotFoundError: No module named 'class_container'
I tried changing the code in helper.py such as:
# helper.py
from helpers.class_container import MyClass
def func():
# some code using MyClass
Then running script.py started working. But when I explicitly run helper.py:
ModuleNotFoundError: No module named 'helpers'
I want to be able run both script.py and helper.py separately without needing to change the code in any module.
Edit: I figured a solution which is changing helper.py such as:
from pathlib import Path
import sys
sys.path.append(str(Path(__file__).parent))
from class_container import MyClass
def func():
# some code using MyClass
Basically I added the directory of helper.py to sys.path by using sys and pathlib modules and __file__ object. And unlike import statement's behaviour, __file__ will not forget it's roots when imported/used from a different module (i.e it won't become the path of script.py when imported into it. It'll always be the path of helper.py since it was initiated there.).
Though I'd appreciate if someone can show another way that doesn't involve messing with sys.path, it feels like an illegal, 'unpythonic' tool.
You have to create a __init__.py file in the MyProject/helpers directory. Maybe you already have created it. If not, create an empty file.
Then in the MyProject/helpers/helper.py, access the module helpers.class_container like this.
from helpers.class_container import MyClass
def func():
# some code using MyClass
You can also use a relative import like this.
from .class_container import MyClass
If you want to run the MyProject/helpers/helper.py independently, add test code in helper.py like this.
from helpers.class_container import MyClass
def func():
# some code using MyClass
if __name__ == '__main__':
func()
And run like this in the MyProject directory.(I assume a Linux environment.)
$ python3 -m helpers.helper
The point is to differentiate Python modules from Python scripts and treat them differently.
Related
Currently, I'm playing around with absolute and relative imports for my tests. Below is the example of the file structure.
File Structure:
project/
main_script.py
input1.csv
input2.csv
Testing/
test_script.py
test_input1.csv
test_input2.csv
test_output.csv
Code in main_script.py
def function1():
{function definition here}
def function2():
{function definition here}
def function3():
{function definition here}
Code in test_script.py
import pytest
from ..main_script import function1, function2, function3
The output I get when running test_script:
ImportError: attempted relative import with no known parent package
From the examples I've read from different sources and tutorials I have watched, this should have been the solution to my problem but it's coming out with more errors. Why is that?
You can try any one of these ways -
Use absolute import
Use standard way of import and remove from keyword
Example: import main_script.function1
Put this inside your package's init.py -
For relative imports to work in Python 3.6 -
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(file)))
And now use normal import statement like :
from main_script import function1
Reference Attached
Do let me know if this helps out.
Happy Learning!!
I would like to import a function foo() from module abc.py
However, abc.py contains other functions which rely on modules which are not available for Python (i.e. I cannot import them into python interpreter, because I use ImageJ to run abc.py as Jython)
One solution I found is to put the problematic imports inside the name == "main" check, such as:
# abc.py
def foo():
print("Hello, World!")
def run_main_function():
foo()
...other stuff using IJ...
if __name__ == "__main__":
from ij import IJ
run_main_function()
So when I try to import foo from into another script def.py, e.g.:
# def.py
from abc import foo
def other_func():
foo()
if __name__ == "__main__":
other_func()
This works. But when I put imports in normal fashion, at the top of the script, I get an error: No module named 'ij'. I would like to know if there is a solution to this problem? Specifically, that I put the imports at the top of the script and then within def.py I say to import just the function, without dependencies of abc.py?
I would like to know if there is a solution to this problem? Specifically, that I put the imports at the top of the script and then within def.py I say to import just the function, without dependencies of abc.py?
As far I know, it's the way that python works. You should put that import in the function that uses it if won't be aviable always.
def run_main_function():
from ij import IJ
foo()
Also, don't use abc as a module name, it's a standard library module: Abstract Base Class 2.7, Abstract Base Class 3.6
Edit: don't use trailing .py when importing as Kind Stranger stated.
i've run through many posts about this, but still doesn't seem to work. The deal is pretty cut. I've the got the following hierarchy.
main.py
DirA/
__init__.py
hello.py
DirB/
__init__.py
foo.py
bla.py
lol.py
The__init__.py at DirA is empty. The respective one at DirB just contains the foo module.
__all__.py = ["foo"]
The main.py has the following code
import DirA
import DirB
hey() #Def written at hello.py
foolish1() #Def written at foo.py
foolish2() #Def written at foo.py
Long story short, I got NameError: name 'foo' is not defined. Any ideas? Thanks in advance.
You only get what you import. Therefore, in you main, you only get DirA and DirB. You would use them in one of those ways:
import DirA
DirA.something_in_init_py()
# Importing hello:
import DirA.hello
DirA.hello.something_in_hello_py()
# Using a named import:
from DirA.hello import something_in_hello_py
something_in_hello_py()
And in DirB, just make the __init__.py empty as well. The only use of __all__ is for when you want to import *, which you don't want because, as they say, explicit is better than implicit.
But in case you are curious, it would work this way:
from DirB import *
something_in_dirb()
By default the import * will import everything it can find that does not start with an underscore. Specifying a __all__ restricts what it imported to the names defined in __all__. See this question for more details.
Edit: about init.
The __init__.py is not really connected to the importing stuff. It is just a special file with the following properties:
Its existence means the directory is a python package, with several modules in it. If it does not exist, python will refuse to import anything from the directory.
It will always be loaded before loading anything else in the directory.
Its content will be available as the package itself.
Just try it put this in DirA/__init__.py:
foo = 42
Now, in your main:
from DirA import foo
print(foo) # 42
It can be useful, because you can import some of your submodules in the __init__.py to hide the inner structure of your package. Suppose you build an application with classes Author, Book and Review. To make it easier to read, you give each class its own file in a package. Now in your main, you have to import the full path:
from myapp.author import Author
from myapp.book import Book
from myapp.review import Review
Clearly not optimal. Now suppose you put those exact lines above in your __init__.py, you may simplify you main like this:
from myapp import Author, Book, Review
Python will load the __init__.py, which will in turn load all submodules and import the classes, making them available on the package. Now your main does not need to know where the classes are actually implemented.
Have you tried something like this:
One way
from DirA import hello
Another way
from DirA.hello import hey
If those don't work then append a new system path
You need to import the function itself:
How to call a function from another file in Python?
In your case:
from DirA import foolish1, foolish2
i'm creating a python program, and i want to split it up into seperate files. I'm using import to do this, but its not working (specifically, a variable is stored in one python file, and its not being read by the main one.
program /
main.py
lib /
__init__.py
config.py
functions.py
I have in main.py:
import lib.config
import lib.functions
print(main)
and config.py has
main = "hello"
I should be getting the output "hello", when i'm executing the file main.py, but i'm not. I have the same problem with functions stored in functions.py
Any help would be great,
Importing the module with a simple import statement does not copy the names from that module into your own global namespace.
Either refer to the main name through attribute access:
print(lib.config.main)
or use the from ... import ... syntax:
from lib.config import main
instead.
You can learn more about how importing works in the Modules section of the Python tutorial.
I'm having a spot of trouble getting my python classes to work within the python console. I want to automatically import all of my classes into the global namespace so I can use them without any prefix.module.names.
Here's what I've got so far...
projectname/
|-__init__.py
|
|-main_stuff/
|-__init__.py
|-main1.py
|-main2.py
|
|-other_stuff/
|-__init__.py
|-other1.py
|-other2.py
Each file defines a class of the same name, e.g. main1.py will define a class called Main1.
My PYTHONPATH is the absolute path to projectname/.
I've got a python startup file that contains this:
from projectname import *
But this doesn't let me use my classes at all. Upon starting a python console I would like to be able to write:
ob=Main1()
but Main1 isn't within the current namespace, so it doesn't work.
I tried adding things to the __init__.py files...
In projectname/__init__.py:
import main_stuff
In projectname/main_stuff/__init__.py:
import other_stuff
__all__ = ["main1", "main2", "main3"]
And so on. And in my startup file I added:
from projectname.main_stuff import *
from projectname.main_stuff/other_stuff import *
But to use the classes within the python console I still have to write:
ob=main1.Main1()
I'd prefer not to need the main1. part. Does anyone know how I can automatically put my classes in the global namespace when using the python console?
Thanks.
==== EDIT ====
What I need is to import a package at the class level, but from package import * gives me everything at the module level. I'm after an easy way of doing something like this:
for module in package do:
from package.module import *
==== ANOTHER EDIT ====
I ended up adding the class imports to my python startup file individually. It's not ideal because of the overhead of maintaining it, but it does what I want.
from class1.py import Class1
from class2.py import Class2
from class3.py import Class3
You want to use a different form of import.
In projectname/main_stuff/__init__.py:
from other_stuff import *
__all__ = ["main1", "main2", "main3"]
When you use a statement like this:
import foo
You are defining the name foo in the current module. Then you can use foo.something to get at the stuff in foo.
When you use this:
from foo import *
You are taking all of the names defined in foo and defining them in this module (like pouring a bucket of names from foo into your module).