When having a project tree like this one
/
└── weird_bug
├── main.py
└── model
├── directions.py
└── weirdo.py
and with this code in the specific classes:
main.py:
from model.directions import Direction
from model.weirdo import Weirdo
def print_direction():
player = Weirdo(Direction.up)
player.print_direction()
if __name__ == '__main__':
print_direction()
directions.py:
from enum import Enum
class Direction(Enum):
up, down = range(2)
and finally weirdo.py:
from directions import Direction
class Weirdo:
def __init__(self, direction):
self.direction = direction
def print_direction(self):
if self.direction == Direction.up:
print(self.direction)
I am receiving this error when I am calling main.py:
ModuleNotFoundError: No module named 'directions'
The error is triggered by the weirdo.py class. I am trying imports around for literally hours and was wondering if someone knows what is happening and can help me understand. Thanks!
When running main.py as an entrypoint, absolute path to directions is model.directions, and that is what needs to be in defined in the weirdo file import.
If you want to avoid specifying full path, you can use relative import in the form of from .directions import Direction in weirdo.py
Related
I'm using Visual Studio Code and I want to use the panel Testing for my unittest tests. It's working for some but not all. Indeed when I import certains locals classes, VSCode doesn't recognize the test. If I remove the import the test is recognize.
Here is one of the class that I'm importing, I reduce it to the maximum:
class ConnectionAWS(InterfaceConnection):
def _connection(self) :
pass
def putFileInS3(self, file):
pass
Here the test :
import unittest
from repertoire.ConnectionAWS import ConnectionAWS
class TestConnectionAWS(unittest.TestCase):
def test_connection_success(self):
self.assertFalse(False)
def test_connection_failure(self):
self.assertFalse(False)
I didn't forget about init.py files.
Here the arborescence :
project
repertoire
ConnexionAWS.py
utils
Log.py
src
__init__.py
test
__init__.py
repertoire
__init__.py
test_connexionAWS.py
utils
__init__.py
test_log.py
test_log.py is recognized even if it's importing Log.py
Can someone explain to me where I'm wrong ?
I am trying to write a library (sort of) for my project. I would like to keep it as modularized as possible. I have a main.py in the root directory and I have two packages required for running the main. I am calling them package1 and package2. The packages in each of them will inherit from their own base packages. The overall tree is as following:
.
├── main.py
├── package1
│ ├── base_package1.py
│ ├── __init__.py
│ └── main_package1.py
└── package2
├── base_package2.py
├── __init__.py
└── main_package2.py
In the file for each package, I am also writing the code to test them. But to test package 2, I also need package 1. My question is about how to import package 1 to package 2. main.py is currently empty. I will share the contents of the remaining files here.
# package1/__init__.py
from .main_package1 import *
# package1/base_package1.py
class BasePackage1:
def __init__(self):
print("init base package 1")
# package1/main_package1.py
from base_package1 import BasePackage1
class MainPackage1(BasePackage1):
def __init__(self):
super().__init__()
print("init main package 1")
if __name__ == "__main__":
# Test MainPackage1
pkg = MainPackage1()
# package2/base_package2.py
class BasePackage2:
def __init__(self):
print("init base package 2")
# package2/main_package2.py
from base_package2 import BasePackage2
class MainPackage2(BasePackage2):
def __init__(self):
super().__init__()
print("init main package 2")
if __name__ == "__main__":
# Option 1
import sys
sys.path.append("../")
from package1 import MainPackage1
# Error:
# ModuleNotFoundError: No module named 'base_package1'
# Option 2
from ..package1 import MainPackage1
# Error:
# ImportError: attempted relative import with no known parent package
What is the correct way to do this? Is there a standard way to do this?
Update: I have found a solution that works for now and posted it as an answer below. If you have a better solution, please post it.
In package2/base_package2.py if you want to reference package1.base_package1 you can import that directly as your current reference point is where main.py is. Absolute imports (those which don't start with a dot) start from your working directory, so you can import package1 from anywhere in package2 and it will be the same.
The reason why you get
ImportError: attempted relative import with no known parent package
is because you are running package2/base_package.py as a main file, which would run as its own script. However, you have provided three files with paths given as package2/base_package.py. I'm assuming that the ones with __main__ are actually main_package1 and main_package2 respectively.
After trying a few other things, I found a solution that seems to be work. I will post it here but will not select it as the accepted answer in case someone comes up with a better and more elegant solution.
In package2/main_package2.py, I did the following import:
import sys
sys.path.append("../package1")
from main_package1 import MainPackage1
I have a Python package mypackage which contains a bunch of modules / classes with this directory structure:
├── interface.py
├── mypackage/
| └── __init__.py
| └── classA.py
| └── classB.py
| └── ...
The current use case is to use interface.py with a bunch of argparse flags:
python interface.py --foo --bar
Inside interface.py it instantiates a bunch of the classes with mypackage and runs their methods. Something like:
from classA import ClassA
def interfaceMethod(foo, bar):
a = ClassA(foo, ...)
print(a.classMethod(bar, ...)
if args.foo: interfaceMethod(args.foo, args.bar)
This works well when getting non-python / programmers to use my code. But I'd like to also be able to import my package within their Python code and run the same methods in interface.py. Something like:
import mypackage
print(mypackage.interfaceMethod(foo, bar)
Question
Is there a standard/best way to do this?
Note: I don't think users need to see my class structure so I'd rather there be one user facing class which implements all of the methods in interface.py
Solution 1 (I don't think this is the preferred solution):
Add methods from interface.py into __init__.py:
# in __init__.py
from classA import ClassA
def interfaceMethod():
a = ClassA(foo)
print(a.classMethod(bar))
Then users can do the following in their own code (it would look very similar in interface.py as well):
import mypackage
mypackage.interfaceMethod()
Solution 2:
Create a mypackage class:
class MyPackage():
self.classA = ClassA(...)
self.classB = ClassB(...)
def interfaceMethod():
a = self.classA()
If I create this class should I worry about the package and class having the same name? Do I change the hierarchy of the package structure to reflect that MyPackage is the forward facing class?
A good way would to use a setup.py and use console_scripts
Put you interface.py inside you package and this to your setup.py:
setup(
# other arguments here...
entry_points={
'console_scripts': [
'script_name = my_package.interface:interfaceMethod',
],
}
)
Change your interface.py to:
from classA import ClassA
def interfaceMethod(foo, bar):
a = ClassA(foo, ...)
print(a.classMethod(bar, ...)
if __name__ == '__main__':
interfaceMethod(args.foo, args.bar)
Once you install with Python setup.py install, you can call your program
from the command line:
script_name --foo --bar
For details see the full documentation.
You can still import it with:
from mypackage import interface
interface.interfaceMethod()
Suppose I have a project organized as follows:
ProjectRoot/
__init__.py
test.py
A/
__init__.py
a_test.py
B/
__init__.py
b_test.py
And suppose that a_test depends on b_test. So the source code is relatively simple:
#
# a_test.py
#
from B.b_test import b_test_class
class a_test_class:
def func(self):
print("a_test_class")
b_instance = b_test_class()
b_instance.func()
if __name__ == "__main__":
a_instance = a_test_class()
a_instance.func()
#
# b_test.py
#
class b_test_class:
def func(self):
print("b_test_class")
#
# test.py
#
from A.a_test import a_test_class
if __name__ == "__main__":
a_instance = a_test_class()
a_instance.func()
As long as I launch test.py script, everything works as intended. Python loads all modules without any troubles and executes them. Now the question comes: how do I launch a_test.py without having test.py? So, basically, what I want to achieve is to cd into projectRoot/A and execute a_test.py. This results in getting ImportError: No module named 'B'
Currently I've been able to create a project with following structure:
ProjectRoot/
customLibModuleA/
...
customLibModuleB/
...
mainApp.py
And what I want to be able to create is following:
ProjectRoot/
customLibModuleA/ #custom protocol implementation
...
customLibModuleB/ #custom logging functions
...
application1/ #server
...
application2/ #client
...
How do I expected to manage complex projects? Any good references to project structuring manuals and styleguides are welcome.
Here's my temporal solution since no one provided pythonic approach.
Folder structure looks like that:
ProjectRoot/
__init__.py
customLibModuleA/ #custom protocol implementation
__init__.py
...
customLibModuleB/ #custom logging functions
__init__.py
...
application1/ #server
__init__.py
__path_setup__.py
server.py
...
application2/ #client
__init__.py
__path_setup__.py
client.py
...
__path_setup__.py content is:
import sys
import os
os.sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
Application scripts have some setup code preceding imports (server.py):
#
#settings up the environment
#
if __name__ == "__main__":
exec(open("./__path_setup__.py").read())
#
# system and libraries imports
#
import customLibModuleA.whatever
...
Hight quality pythonic solution to this problem is still welcome.
I feel like this should be an easy mock, but I have not gotten it to work yet.
I am working off of the following directory structure:
module
├── utilities.py
├── order.py
├── test
│ ├── test_order.py
The relevant code is as follows:
-- utilities.py --
def get_file_path(order_number, file_extension):
# this is what I want to mock out
-- order.py --
from module.utilities import get_file_path
class Order():
# ...
#classmethod
def load_order(order_number, extension):
file_path = get_file_path(order_number, extension)
-- test_order.py --
import unittest
from unittest.mock import patch
from module.order import order
#patch('order.get_file_path')
def mock_file(_, extension):
if extension == 'json':
return static_file_path
class TestOrder(unittest.TestCase):
def test_load_order_by_number(self):
my_order = order.load_order(number, extension)
This is the first time that I have tried mocking in Python. From what I can tell, what I have should work, but whenever an Order calls get_file_path, it always uses the one in utilities.py.
I have tried:
decorating test_load_order_by_number
patching with module.order.get_file_path
I tried looking on SO but none of the solutions that I found helped, so I thought that I was just doing something obviously wrong that someone can point out.
It does not look like creating the patch outside of the class was getting picked up. It started working when I pulled the patch in as a decorator for the specific test.
class TestOrder(unittest.TestCase):
#patch('utilities.order.get_file_path')
def test_load_order_by_number(self, file_mock):
def mock_get_file_path(*args, **kwargs):
if kwargs.get('extension', None) == 'json':
return static_file_path
return None
file_mock.side_effect = mock_get_file_path
my_order = order.load_order(number, extension)