Python class instance circular referencing in different files using 'IMPORT AS' - python

I am encountering a problem using a circular importation in Python 2.7
For some reasons, I need this structure, here reduced for the explanation to 4 python files :
- main.py
- folder
\- __init__.py
\- loader.py
\- folder1
\- __init__.py
\- class1.py
\- folder2
\- __init__.py
\- class2.py
main.py :
import folder.loader as LD
LD.a.change_class2()
LD.b.change_class1()
loader.py :
from folder1.class1 import Class1
from folder2.class2 import Class2
a=Class1()
b=Class2()
class1.py :
import folder.loader as LD
class Class1():
def __init__(self):
self.pty1=0
def change_class2(self):
LD.b.pty2=2
class2.py :
import folder.loader as LD
class Class2():
def __init__(self):
self.pty2=0
def change_class1(self):
LD.a.pty1=6
The code executed is main.py. This script calls the file loader.py which creates an instance for Class1 and Class2. The instances have to communicate and modify each other, explaining the necessity (if I am not wrong) of the file loader.py.
Executing this code returns the error from class1.py :
import folder.loader as LD
AttributeError: 'module' object has no attribute 'loader'
I have no idea of what is going on here.
Surprisingly, when I remove the part as LD from the importation command line in the classes files, it works perfecly :
class1.py :
import folder.loader
class Class1():
def __init__(self):
self.pty1=0
def change_class2(self):
folder.loader.b.pty2=2
class2.py :
import folder.loader
class Class2():
def __init__(self):
self.pty2=0
def change_class1(self):
folder.loader.a.pty1=6
For this example, it's ok, but in the real program I am trying to make, based on this structure, I can't use the complete module path each time I need to communicate with another class instance.
Why am I getting this error ? What can I do to solve this ?
Thank you in advance for your help.
EDIT : replacing import folder.loader as LD by from .. import loader as LD now returns another error, that I don't understand :
from .. import loader as LD
ImportError: cannot import name loader

I solved the problem simply by using Python 3, without code changes.

Related

Python import that works with directory and package

I have two classes (in the same directory), one derived from the other.
ClasssA.py contains the following code:
class ClassA():
def __init__(self):
pass
ClasssB.py contains the following code:
from ClassA import ClassA
class ClassB(ClassA):
def __init__(self):
ClassA.__init__(self)
This works fine when I run scripts from the Python console.
I want to build these into a package, but when I do and try to instantiate ClassB, I get an error:
No module named 'ClassA'
How can I write the import statement and/or __init__.py so the code works in both scenarios.
Thanks for any suggestions.
1) Create a module named classA containing two files init.py(Empty file) and temp.py
temp.py
class ClassA():
def __init__(self):
print('ClassA')
2) ClassB.py
from ClassA.temp import ClassA
class ClassB(ClassA):
def __init__(self):
super.__init__()
All this should in same folder
Use from filename import ClassA to indicate which file in the directory you are importing from.

Python3 relative imports

I'm tired of reading one-off use cases of relative imports so I figured I'd as a question to get an example of how to do a relative import from a directory above and bellow, for both importing module functions and class objects.
directory structure:
.
├── lib
│   ├── __init__.py
│   └── bar.py
└── src
├── main.py
└── srclib
├── __init__.py
└── foo.py
bar.py
def BarFunc():
print("src Bar function")
class BarClass():
def __inti__(self):
print("src Bar Class")
def test(self):
print("BarClass working")
foo.py
def FooFunction():
print("srclib Foo function")
class FooClass():
def __init__(self):
print("srclib Foo Class")
def test(self):
print("FooClass working")
Question: What is the syntax in python 3 to import for these use cases?
main.py
# What is the syntax to import in python 3?
# I want to be able to call FooFunc()
foo.FooFunc()
# I want to be able to create a FooClass() object
foo_class = foo.FooClass()
foo_class.test()
# I want to be able to call FooFunc()
bar.BarFunc()
# I want to be able to create a BarClass() object
bar_class = bar.BarClass()
bar_class.test()
It all depends on where you start your python interpreter from. In your case, I would suggest you to start the interpreter from your project's root directory while making the following changes:
In file src/srclib/__init__.py add:
from . import foo
The reason for doing this is to explicitly state in your __init__.py file what to import from your module.
In your main.py file, add the following:
from lib import bar
from src.srclib import foo
Hope this helps!

Execute sh in subdirectory from main.py script?

I am trying to do the following thing.
I have a python project with this dir-tree:
Project dir
|
|___main.py
|___module
|
|__a.py
|__a.sh
a.py has a class with a method that runs the script:
class A():
def run():
os.system('a.sh')
And a.sh creates a file:
touch a.txt
And main.py instantiates an object of class A and calls run():
a = A()
a.run()
When main is called, I get an error saying that the script a.sh is not found. I get why that happens, it's because the working dir is equal to the project root path, but how can I make it work so that the file created ends up in the root path?
I want to call main.py and end up with this configuration.
Project dir
|
|___a.txt
|___main.py
|___module
|
|__a.py
|__a.sh
I could replace the call to a.sh in a.py to
os.system('module/a.sh')
And it would work, but it does not look clean to me.
Code in the a.py module can extract the name of the directory it is in and use that in the os.system() call. This is what I mean:
File a.py:
import os
class A():
def run(self):
my_directory = os.path.dirname(__file__)
script_path = os.path.join(my_directory, 'a.sh')
os.system(script_path)
a = A()
a.run()

Python - Intra-package importing when package modules are sometimes used as standalone?

Sorry if this has already been answered using terminology I don't know to search for.
I have one project:
project1/
class1.py
class2.py
Where class2 imports some things from class1, but each has its own if __name__ == '__main__' that uses their respective classes I run frequently. But then, I have a second project which creates a subclass of each of the classes from project1. So I would like project1 to be a package, so that I can import it into project2 nicely:
project2/
project1/
__init__.py
class1.py
class2.py
subclass1.py
subclass2.py
However, I'm having trouble with the importing with this. If I make project1 a package then inside class2.py I would want to import class1.py code using from project1.class1 import class1. This makes project2 code run correctly. But now when I'm trying to use project1 not as a package, but just running code from directly within that directory, the project1 code fails (since it doesn't know what project1 is). If I set it up for project1 to work directly within that directory (i.e. the import in class2 is from class1 import Class1), then this import fails when trying to use project1 as a package from project2.
Is there a way to have it both ways (use project1 both as a package and not as a package)? If there is a way, is it a discouraged way and I should be restructuring my code anyway? Other suggestions on how I should be handling this? Thanks!
EDIT
Just to clarify, the problem arrises because subclass2 imports class2 which in turn imports class1. Depending on which way class2 imports class1 the import will fail from project2 or from project1 because one sees project1 as a package while the other sees it as the working directory.
EDIT 2
I'm using Python 3.5. Apparently this works in Python 2, but not in my current version of python.
EDIT 2: Added code to class2.py to attach the parent directory to the PYTHONPATH to comply with how Python3 module imports work.
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
Removed relative import of Class1.
Folder structure:
project2
- class3.py
- project1
- __init__.py
- class1.py
- class2.py
project2/project1/class1.py
class Class1(object):
def __init__(self):
super(Class1, self).__init__()
self.name = "DAVE!"
def printname(self):
print(self.name)
def run():
thingamy = Class1()
thingamy.printname()
if __name__ == "__main__":
run()
project2/project1/class2.py
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from class1 import Class1
class Class2(Class1):
def childMethod(self):
print('Calling child method')
def run():
thingamy = Class2()
thingamy.printname()
thingamy.childMethod()
if __name__ == "__main__":
run()
project2/class3.py
from project1.class2 import Class2
from project1.class1 import Class1
class Class3(Class2):
def anotherChildMethod(self):
print('Calling another child method')
def run():
thingamy = Class3()
thingamy.printname()
thingamy.anotherChildMethod()
if __name__ == "__main__":
run()
With this setup each of class1, 2 and 3 can be run as standalone scripts.
You could run class2.py from inside the project2 folder, i.e. with the current working directory set to the project2 folder:
user#host:.../project2$ python project1/class2.py
On windows that would look like this:
C:\...project2> python project1/class2.py
Alternatively you could modify the python path inside of class2.py:
import sys
sys.path.append(".../project2")
from project1.class1 import class1
Or modify the PYTHONPATH environment variable similarly.
To be able to extend your project and import for example something in subclass1.py from subclass2.py you should consider starting the import paths always with project2, for example in class2.py:
from project2.project1.class1 import class1
Ofcourse you would need to adjust the methods I just showed to match the new path.

How do I properly reference Python classes?

I'm working on writing my first Python class. Being the java programmer that I am, I have something like this:
#class1.py
class class1:
def __init__(self):
#Do stuff here
And in my current script:
import class1
object = class1()
I'm getting a Name Error: name 'class1' is not defined
I've also tried this, with no luck:
import class1
object = class1.class1()
The error I get here is AttributeError: 'module' object has no attribute 'class1'
What am I doing wrong?
Python import is by module and then by the contents of the module, so for your class1.py it becomes:
from class1 import class1
Python module docs
In Python you import the modules. For class1.py file you can use:
from class1 import class1
Or if you have more than one....
from class1 import *

Categories

Resources