Maintain separate class files in python - python

I have to admit that I am fairly a newbie to python. This question is more related to code organization.
For example, here is app.py file
import backtracker as bt
# Create a class
class TestTracker(bt.Strategy):
def log(self, txt, dt=None):
''' Logging function for this strategy '''
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def __init__(self):
self.dataclose = self.datas[0].close
self.datapoint = self.datas[0]
def next(self):
self.log('Close, %2f' %self.dataclose[0])
Now, I would like to separate class file to testStrategy.py and import it into app.py. The folder structure would look something like this
|
|-strategies
| |-testStrategy.py
|-app.py
How do I reference base class bt.strategy in my new class file ?
Thank you for your help.

There are two ways you can go about it.
Add the folder strategies to sys.path and then import your class.
# This gives you the folder in which current file resides
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
if BASE_DIR + '/strategies' not in sys.path:
sys.path.append(BASE_DIR + '/strategies')
from testStrategy import TestTracker
Add __init__.py in every folder and then use your code as a python package. This allows you to import in the following way.
import strategies.testStrategy.TestTracker
Be wary of the trap though.

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

Concatenate Python Files Together to Simplify Imports

I have a directory of code filled in like this:
root_dir
├── root.py
├── same_step_0.py
├── same_step_1.py
├── same_step_2.py
└── utils
├── __init__.py
├── file_one.py
└── file_two.py
The root.py file references the functions in the same_step files. For example:
# In root.py
same_step_0.generated_function()
The "step" files have references to functions in the 'utils' directory, with a simple import and call - e.g.
from utils.file_one import function_one
function_one(val="somelongstring")
Ok, now we get to the problem - I'm working against an API which effectively requires each "step" to be a single python file. So, what I need to do is, somehow, append all functions pulled in by each step file into a single file which I can then submit to the service.
IDEALLY, I'd love to do this with as little changes to the underlying code. So, if possible, in same_step_0 I'd like to leave it as:
from utils.file_one import function_one
function_one(val="somelongstring")
and not have to change it to
# Note removing the 'utils' prefix
from file_one import function_one
function_one(val="somelongstring")
So, the question is, is there a way I can append all the dependent files or functions together into a single file such that it mimic'd import behavior? Or at least function call behavior? Ideas I've thought about:
Pickling all subfiles into a serialization format and inserting at the end of the code
Raw appending of all python files - perhaps inside an inline module?
Scraping all files for functions and attaching them manually (however, this would not preserve namespacing)
I haven't dug into these yet - I'm curious if this is even possible
I can do a lot of generation and wrapping of code, but I'd prefer not to touch the inner code (the function_one call, for example).
Goal
To create a minimal set of scripts, and an interchange format that can be stored in a Python executable to recreate a module structure.
Source
Ok here's a simple example that abuses types.ModuleType, sys, and globals() to do this:
import os
import sys
import types
class Module:
def __init__(self, name, source=None, path=None, modules=None):
self.name = name
self.source = source
self.path = path
self.modules = modules
def from_file(name, path):
return Module(name, open(path).read(), path)
def from_dir(name, path):
return Module(name, None, path, [])
def __repr__(self):
return f'Module(name={repr(self.name)}, source={repr(self.source)}, path={repr(self.path)}, modules={self.modules})'
def to_dict(self):
data = { 'name': self.name }
if self.source is not None:
data['source'] = self.source
if self.path is not None:
data['path'] = self.path
if self.modules is not None:
data['modules'] = [i.to_dict() for i in self.modules]
return data
#staticmethod
def from_dict(data):
modules = None
if 'modules' in data:
modules = [Module.from_dict(i) for i in data.pop('modules')]
return Module(**data, modules=modules)
def get_modname(parent, module):
if parent is None:
return module
if module == '__init__':
return parent
return f'{parent}.{module}'
def compile_module(module, parent=None):
modname = get_modname(parent, module.name)
mod = types.ModuleType(modname)
exec(module.source, mod.__dict__)
path = os.path.realpath(module.path)
mod.__path__ = os.path.dirname(path)
mod.__file__ = path
sys.modules[modname] = mod
globals()[modname] = mod
return mod
def compile_module_recursive(package, parent=None):
# Need to do this recursively.
mod = compile_module(package, parent)
if not package.modules:
return mod
for submodule in package.modules:
submod = compile_module_recursive(submodule, parent=get_modname(parent, package.name))
if not hasattr(mod, submodule.name):
setattr(mod, submodule.name, submod)
return mod
def read_module_recursive(directory, parent=None):
# The module order is first the:
# 1. All submodules
# 2. Then definitions inside
# Then, need to define `__name__`, `__path__` and `__file__`.
cwd = os.getcwd()
realpath = os.path.realpath(directory)
parent_dir = os.path.dirname(realpath)
base_dir = os.path.basename(realpath)
if parent is None:
parent = Module.from_dir(base_dir, realpath)
os.chdir(realpath)
for entry in os.listdir(realpath):
path = os.path.join(realpath, entry)
if os.path.isfile(path):
name, ext = os.path.splitext(entry)
if not ext == '.py':
continue
if name == '__init__':
parent.path = path
parent.source = open(path).read()
else:
parent.modules.append(Module.from_file(name, path))
elif os.path.isdir(path):
if entry == '__pycache__':
continue
path = os.path.join(realpath, entry)
# Must have processed __init__.py
if not os.path.isfile(f'{path}/__init__.py'):
continue
module = Module.from_dir(entry, path)
parent.modules.append(module)
read_module_recursive(entry, module)
os.chdir(cwd)
return parent
# SAMPLE USE
# ----------
# module = read_module_recursive('mylib')
# data = module.to_dict() # can store as a Python dict.
# module = Module.from_dict(data)
# compile_module_recursive(module)
How it works
Basically, it reads all .py files from all modules, recursively. It currently does not support extension types, only pure Python files. It then creates an intermediate, tree-like type for the entire module tree. It provides easy serialization to and from dict, so it's much easier to copy-and-paste it into your executable file.
Example use
Say I have the following directory structure:
mylib/
__init__.py
a.py
b.py
c/
__init__.py
d.py
It properly respects the import order, and how it variable assignments override imports or submodules. Please note that it imports everything recursively all at once, which differs than the traditional import structure.
mylib/init.py
a = 'e'
mylib/a.py
def afunc(a):
return str(a)
class AClass:
def x(self):
return 1
mylib/b.py
def bfunc(b):
return repr(b)
class BClass:
def x(self):
return 1
mylib/c/init.py
mylib/c/d.py
def dfunc(d):
return str(d)
class DClass:
def x(self):
return 1
Example
>>> module = read_module_recursive('mylib')
>>> data = module.to_dict() # can store as a Python dict.
>>> module = Module.from_dict(data)
>>> compile_module_recursive(module)
>>> mylib
<module 'mylib' from 'C:\\Users\\user\\OneDrive\\Desktop\\lib\\mylib\\__init__.py'>
>>> mylib.a
'e'
>>> from mylib.a import afunc # still works
>>> afunc(54)
'54'
>>> import mylib # works because `'mylib'` is in `sys.modules`.
Congrats: this is a hack, but it works, and it works nicely, and it uses Python's own packaging system to do everything, so it's much more resilient than copying and pasting. After compiling, it also respects imports (due to adding them to sys.modules). It also respects __doc__, and other attributes.
License
Public Domain or Unlicensed. Use as you see fit. Attribution would be nice, but not required.

Why can't I reference this class from another app in my Django project?

I'm using Django and Python 3.7. I have two applications in my project -- common and mainsite . In common, I have a file "model_utils.py" at the root of my application (right next to models.py). It contains this code
class RawCol(Expression):
def __init__(self, model, field_name):
field = model._meta.get_field(field_name)
self.table = model._meta.db_table
self.column = field.column
super().__init__(output_field=CharField())
def as_sql(self, compiler, connection):
sql = f'"{self.table}"."{self.column}"'
return sql, []
How do I reference this class from my other application, "mainsite"? I put this at the top of one of my files in mainsite ..
from common import RawCol
but when I run some tests, I get this error ...
ImportError: cannot import name 'RawCol' from 'common' (/Users/davea/Documents/workspace/mainsite_project/common/__init__.py)
Edit: Project structure at the top level directories looks like ...
+ common
+ mainsite
+ mainsite_project
+ manage.py
+ templates
+ venv
Try from common.model_utils import RawCol
instead of from common import RawCol
You always need to specify the exact .py file (without the .py ending) to import from.
If it still doesn't work, it can be a circular import problem.
If you try to import something from mainsite.model into common.model_utils and the other way around, you are creating an impossible import loop.
You can fix this by creating a seperate file like common/dependent_model.py and putting only the RawCol() class in there without any import from mainsite. Like this, the both files are not importing from each other (which doesn't work).

Python Error Import Class another directory

I have structure project python
MyProject
+Classes
-stage_competition.py
main.py
Executing Python (main.py) - Show error "ModuleNotFoundError("No module named 'Classes'",)"
I tried import direct, but is not working too, always showing same error
from Classes.stage_competition import Stage_competition
item = Stage_competition("field1", "field2", "field3" , "field4")
Create class Stage_competition
class Stage_competition(object):
"""description of class"""
def __init__(self, type_competition, datalake, competition ,hour):
self.type_competition = type_competition
self.datalake = datalake
self.competition = competition
self.hour = hour
def settype_competition(self, type_competition):
self.type_competition = type_competition
def setdatalake(self, datalake):
self.datalake = datalake
def getcompetition(self):
return self.competition
def gethour(self):
return self.hour
If the Classes is in the same folder as main.py, you should import it this way (notice the dot before Classes):
from .Classes.stage_competition import Stage_competition
Alternatively, you could add directory to Classes to PYTHONPATH, which allows you to import Classes from anywhere.

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