How to solve this Python import circular reference - python

I have a class JCheq, with a static var named 'logger'.
JCheq imports module printing_systems, but I need to use JCheq.logger from printing_systems.
My code does not compile after I put import JCheq in printing_systems.py.
jcheq.py
from printing_systems import printing_systems
from logger import logger
class JCheq:
logger = logger.Logger('logs/jcheq.log', loglevel=logger.Logger.INFO)
def __init__(self):
pass
...
printing_systems/printing_systems.py
from jcheq import JCheq
class WinLPR:
def __init__(self):
pass
#staticmethod
def send(spool, params):
temp_dir = tempfile.mkdtemp()
try:
JCheq.logger.log('Creando archivo temporal en dir: ' + temp_dir, logger.Logger.TRACE)
Error trace:
Traceback (most recent call last):
File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/jcheq.py", line 12, in <module>
from printing_systems import printing_systems
File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/printing_systems/printing_systems.py", line 7, in <module>
from jcheq import JCheq
File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/jcheq.py", line 12, in <module>
from printing_systems import printing_systems
ImportError: cannot import name 'printing_systems'

Moving the import statement in the function is commonly used to solve circular imports. It is handy in cases when restructuring your application would be too costly (if useful at all).
Another solution would be to move JCheq.logger into its own module that both jcheq.py and printing_systems/printing_systems.py would import.
Or, you could make logger.Logger a factory function backed by some registry (or simply memoize it) so that it returns the same logger when the same arguments are given. This way, printing_system.py would simple import logger instead of importing jcheq.

Related

Some question about python's inheritance, import

I'm new to python, but skilled on java. Now I'm facing a annoying question when training on python3.5, I have such a src structure:
/project-root
--main.py
--ModelImpl.py #subclass of BaseModel
--ActionImpl.py #subclass of BaseAction
--/base
----BaseModel.py #base class of all
----BaseAction.py #subclass of BaseModel
----modulescript.py
in main.py:
from ModelImpl import ModelImpl
from ActionImpl import ActionImpl
modelImpl = ModelImpl()
actionImpl = ActionImpl()
in modulescript.py:
from BaseAction import BaseAction
baseAction = BaseAction()
in BaseModel.py:
class BaseModel:
def __init__(self):
print("BaseModel")
in BaseAction.py:
from .BaseModel import BaseModel
class BaseAction(BaseModel):
def __init__(self):
super().__init__()
print("BaseAction")
in ModelImpl.py:
from base.BaseModel import BaseModel
class ModelImpl(BaseModel):
def __init__(self):
super().__init__()
print("ModelImpl")
in ActionImpl.py:
from base.BaseAction import BaseAction
class ActionImpl(BaseAction):
def __init__(self):
super().__init__()
print("ActionImpl")
Now when I input python3 main.py in terminal, I got printed result:
BaseModel
ModelImpl
BaseModel
BaseAction
ActionImpl
but if I input python3 module function.py, I got error:
Traceback (most recent call last):
File "modulescript.py", line 1, in (module) from BaseAction import BaseAction
File "/home/jerry/projects/test/python/base/BaseAction.py", line 1, in (module) from .BaseModel import BaseModel SystemError: Parent module '' not loaded, cannot perform relative import
I found that It's cause by import statement in BaseAction.py:
from .BaseModel import BaseModel
If I change to from BaseModel import BaseModel, the modulescript.py runs ok, but the main.py will got a error:
File "main.py", line 225, in (module) from ActionImpl import ActionImpl
File "/home/jerry/projects/test/python/ActionImpl.py", line 1, in (module) from base.BaseAction import BaseAction
File "/home/jerry/projects/test/python/base/BaseAction.py", line 1, in (module) from BaseModel import BaseModel
ImportError: No module named 'BaseModel'
Oops. annoying!
In java, you can import any Class from any where if you provide the right path of the class like import com.domain.MyClass;
so, what's the right way to import in python?
This is Python, not Java, you group modules related to eachother in a single package, which is a folder.
To be able to import from a package, you must do a few things first.
Create __init__.py in your package to let interpreter know that it's a package. If there's no such file in a folder, it won't even budge whether you want to import from there or not, it's not a package to it and that's all.
Additionally, if you want (and you should when you're creating a package for others to use) import classes functions and etc in your __init__.py to allow to import them from the package itself directly.
I made a simple example:
project tree:
/root
test.py
/examplepkg
__init__.py
somemodule.py
EDIT: if you want examplepkg to have a "nested" package, as in, package it depends on in some way, you create another folder, and put another __init__.py in it and do the same thing, then in __init__.py of examplepkg you can further "export" it for the top level modules to see. How you do it is up to you, just be consistent.
somemodule.py:
class SomeClass:
def __init__(self):
print("New Instance of SomeClass!")
__init__.py:
from .somemodule import SomeClass # you could see it as exporting
test.py:
from examplepkg import SomeClass
SomeClass()
For more information, read this.
I got the same error but the error got fixed when I changed
from .BaseModel import BaseModel
to
from base.BaseModel import BaseModel

Python: class not callable from separate file?

I have a class, robot, in a file called robot.py
I want to create a robot instance in my main script like so:
in robot.py:
class robot(object):
def __init__(self,pygame,screen_width,screen_height):
in main.py:
import pygame, sys, copy
import mouse
import robot
import menu
import button
from pygame.locals import *
...
size = [1200,900]
my_robot = robot(pygame,size[0]-400,size[1]-100)
error:
me:cup-robot Me$ python run.py
Traceback (most recent call last):
File "run.py", line 24, in <module>
my_robot = robot(pygame,size[0]-400,size[1]-100)
TypeError: 'module' object is not callable
how do I do this?
Two choices :
import robot and then prefix all with robot :
my_robot = robot.robot(pygame,size[0]-400,size[1]-100)
or
from robot import robot and then your code should work. But then, you can see that you won't be able to distinguish if robot is a module or the class, so you should not name the class and the file with the same name.
Change your import statement:
from robot import robot
You have robot defined both as a module (robot.py) as well as a class. You need to import the class from the module so it is publicly available.

static method in Python not working

I'm learning by my self Python and I have a mind blowing issue, because I don't understand why is not working. I'm using PyDev and I've download version 2 of Python. I have this code:
class Utils:
#staticmethod
def hello():
print "Hi! I'm the Utils class"
Utils.hello() #Hi! I'm the Utils class
and everything is working fine at this point. But if I import the Utils class and call the static method from another module...
import Utils
Utils.hello()
I get this error:
Traceback (most recent call last):
File "C:\Users\migugonz\Desktop\Docs\Per Folder\WorkSpacePy\Rosalind\src\bioinformatics\stronghold\Pruebas.py", line 40, in <module>
Utils.hello()
AttributeError: 'module' object has no attribute 'hello'
I thing it can't be a big deal, but I've been searching a solution and as long I know this shlould be work.
I believe you need to do Utils.Utils.hello()
or import like from Utils import Utils

global name 'class' is not defined - Python

I defined a class called Parser in a file called parser.py, that parses a test result....
import sys
import re
class Parser:
def __init__(self):
pass
def udp_parse(self, filename=""):
# ... some code over here
Now, in main.py. I have:
from dbconn import *
from parser import *
import os
import subprocess
def main()
dbconn = Dbconn()
parse = Parser()
# more code here ...
if __name__ == '__main__':
main()
and I'm getting:
Traceback (most recent call last):
File "iperf.py", line 108, in <module>
main()
File "iperf.py", line 49, in main
parse = Parser()
NameError: global name 'Parser' is not defined
parser.py is in the same directory as dbconn.py and main.py. Dbconn() works without any problem, but I'm not understanding why Parser() can't work too ...
Parser is an existing python module. Use a different file name (not parser.py) or insert your path in sys.path before stdlibs.
import sys
sys.path.insert(0,'parser/directory')
from parser import *

python import error, import class from another file

I am trying to import the class PBase which is in base.py(its in the same folder)
So I am doing the following
from base import PBase
but I am getting the following error
Traceback (most recent call last):
File "test_pricing.py", line 9, in <module>
from base import PBase
ImportError: cannot import name PBase
here is my base.py
import yaml
import unittest, time, re
class PBase(unittest.TestCase):
def enter_credentials(self, username, password):
self.driver.find_element_by_id("id_username").clear
self.driver.find_element_by_id("id_username").send_keys(username)
self.driver.find_element_by_id("id_password").clear
self.driver.find_element_by_id("id_password").send_keys(password)
self.driver.find_element_by_css_selector("input.btn.btn-success").click()
def get_credentials(self):
with open('credentials.yml', 'r') as f:
doc=yaml.load(f)
return doc
def is_user_logged_in(self):
f= "Account" in self.driver.find_element_by_css_selector(".navbar").text
return f
def log_in_user(self):
self.driver.get(self.login_url)
user_dict=self.get_credentials()
username=user_dict["user"]["username"]
password=user_dict["user"]["password"]
self.enter_credentials(username, password)
self.assertEqual(self.expected_logged_in_title, self.driver.title)
def wait_for_chat_window(self, timeout=5):
WebDriverWait(self.driver, timeout, poll_frequency=0.1).until(lambda b: b.find_element_by_id('habla_beta_container_do_not_rely_on_div_classes_or_names').is_displayed())
time.sleep(3)
def close_modal_window(self):
driver=self.driver
driver.find_element_by_xpath('//a[#class="close"]').click()
def tearDown(self):
if self.is_final_test==1:
self.driver.quit()
This might be an issue caused by importing in a circular way. For example one tries to import from Bar from bar.py that requires Foo from foo.py that requires Utils that is defined in bar.py:
foo.py:
from bar import Utils
class Foo:
def __init__(self):
print("hello, from Foo")
Utils.do_something()
and bar:
from foo import Foo
class Utils:
#staticmethod
def do_something():
print("done something")
class Bar(Foo):
def __init__(self):
print('Hi, from Bar')
This gives similar issues where one can import bar inside foo.py without any issue, but once one tries to make any reference to the class Utils inside foo.py one gets various errors, for example the previous code results in:
Traceback (most recent call last):
File "main.py", line 1, in <module>
from bar import Bar
File "bar.py", line 1, in <module>
from foo import Foo
File "foo.py", line 1, in <module>
from bar import Utils
ImportError: cannot import name 'Utils' from 'bar' (bar.py)
The issue is easily solved by placing Utils in its own file.

Categories