If I have a python file as follows
import time
class abc:
def func1(self):
while True:
do something
time.sleep(5)
xyz = abc()
xyz.func1()
The above works exactly as expected
If I move the class definition out to a seperate .py file and import it
import time
from test1 import abc
xyz = abc()
xyz.func1()
Works as expected until it hits the time.sleep(5) when it errors
saying time is not defined
I have tried adding the time import into the class definition but
still seem to get the same problem
What am I missing.
Moving the import to the class definition file doesn't seem to resolve the problem, either adding it at the top or in the init .
Take a look at the python documentation about the import statement.
Quote from there:
define a name or names in the local namespace for the scope where the import statement occurs.
So your toplevel import is bound on module level and the name time is accessible from wherever in that module.
If you move the import inside the method, it will be accessible in the local scope of the method and won't be visible outside of that method.
So, you don't want to move the import in your other module, as you don't use it there. To make things work, you should preserve the import of time where it is now and only move your function calls outside:
# test1.py
import time
class ABC:
def func1(self):
while True:
# do something
time.sleep(5)
print('slept 5 secs')
# main.py
from test1 import ABC
abc = ABC()
abc.func1()
[Not related to your question tip] You should also take a look at PEP8 and follow it's conventions.
Related
I want add a method to a class, without extending another class (for the import statements should be unaltered).
Conceptually, my current approach is:
add_method.py
def new_method():
pass
MyObject.new_method = new_method
main.py
from package import MyObject
import add_method
ob = MyObject()
ob.new_method()
This does the job, however, PyCharm does not recognize that the import add_method import statement is acutally used: "Unused import statement". Is there an elegant way to obtain the same effect with PyCharm recognizing the import?
I'm new to python. This is not my actual case, it's just my curiosity about importing nested class.
So I have a main.py and test.py.
test.py:
class one():
class two():
def twodef():
pass
so in my main.py, I can do 'import test' or 'from test import one'. But I got error when do: 'from test.one import two'.
error : ImportError: No module named one
Anyone can explain this?
You can only do from module import name for names that exist in the module's global scope - basically, names that are defined in top-level module code. Names that are defined in lower-level scopes - for example within classes as in your example - are not importable. You need to import the object that contains the name, and access it from there.
from test import one
my_two = one.two()
You could do the following:
from test import one
two_object = one.two()
two_object.twodef()
inside test.py
class One:
class Two:
#staticmethod
def twodef():
print("twodef")
My main logic:
from test import One
two_obj = One.Two
two_obj.twodef()
Remove the parenthesis at the end of class definition.
Coding standards:
Always declare your class names in upper camel case (class one => class One).
For more about scope
Preference:
And if you have a single class inside python file, always name that file in that class name but in lower camel case. (test.py => one.py). I have thought this as a standard earlier, but seems its practiced widely. I would use this because, if then project size grew and if you end up having a lot of classes and modules, it's logical and easy to access, rather than visiting the module to find the class name.
Ref1
Ref2
I am writing a Python script where some of the core functionalities can be done by another existing library. Unfortunately, while that library has more features, it is also slower, so I'd like if the user could at runtime select whether they want to use that library or my own fast and simple implementation. Unfortunately I'm stuck at a point where I don't understand some of the workings of Python's module system.
Suppose that my main program was main.py, that the (optional) external module is in module_a.py and that my own fast and simple implementation of module_a together with the actual program code that uses either my own implementation or the one of module_a is in the file module_x.py:
main.py:
import module_x
module_x.test(True)
module_x.test(False)
module_a.py:
class myclass():
def __init__(self):
print("i'm myclass in module_a")
module_x.py:
class myclass():
def __init__(self):
print("i'm myclass in module_x")
def test(enable_a):
if enable_a:
try:
from module_a import myclass
except ImportError:
global myclass
enable_a = False
else:
global myclass
i = myclass()
When I now execute main.py I get:
$ python3 main.py
i'm myclass in module_a
i'm myclass in module_a
But why is this? If False is passed to test() then the import of the module_a implementation should never happen. Instead it should only see myclass from the local file. Why doesn't it? How do I make test() use the local definition of myclass conditionally?
My solution is supposed to run in Python3 but I see the same effect when I use Python2.7.
An import statement is permanent within the thread of execution unless it is explicitly undone. Furthermore, once the from ... import statement is executed in this case, it replaces the variable myclass in the global scope (at which point the class it was previously referencing defined in the same file is no longer referenced and can in theory be garbage collected)
So what is happening here is whenever you run test(True) the first time, your myclass in module_x is effectively deleted and replaced with the myclass from module_a. All subsequent calls to test(False) then call global myclass which is effectively a no-op since the global myclass now refers to the one imported from the other class (and besides the global call is unneeded when not changing the global variable from a local scope as explained here).
To work around this, I would strongly suggest encapsulating the desired module-switching behavior in a class that is independent of either module you would like to switch. You can then charge that class with holding a reference to both modules and providing the rest of you client code with the correct one. E.g.
module_a_wrapper.py
import module_x
import module_a
class ModuleAWrapper(object):
_target_module = module_x # the default
#classmethod
def get_module(cls):
return cls._target_module
def set_module(enable_a):
if enable_a:
ModuleAWrapper._target_module = module_a
else:
ModuleAWrapper._target_module = module_x
def get_module():
return ModuleAWrapper.get_module()
main.py:
from module_a_wrapper import set_module, get_module
set_module(True)
get_module().myclass()
set_module(False)
get_module().myclass()
Running:
python main.py
# Outputs:
i'm myclass in module_a
i'm myclass in module_x
You can read more about the guts of the python import system here
The answer by lemonhead properly explains why this effect happens and gives a valid solution.
The general rule seems to be: wherever and however you import a module, it will always replace any variables of the same name from the global scope.
Funnily, when I use the import foo as bar construct, then there must neither be a global variable named foo nor one named bar!
So while lemonhead's solution worked it adds lots of complexity and will lead to my code being much longer because every time I want to get something from either module I have to prefix that call with the getter function.
This solution allows me to solve the problem with a minimal amount of changed code:
module_x.py:
class myclass_fast():
def __init__(self):
print("i'm myclass in module_x")
def test(enable_a):
if enable_a:
try:
from module_a import myclass
except ImportError:
enable_a = False
myclass = myclass_fast
else:
myclass = myclass_fast
i = myclass()
So the only thing I changed was to rename the class I had in global scope from myclass to myclass_fast. This way it will not be overwritten anymore by the import of myclass from module_a. Then, on demand, I change the local variable myclass to either be the imported module or myclass_fast.
Does it matter where modules are loaded in a code?
Or should they all be declared at the top, since during load time the external modules will have to be loaded regardless of where they are declared in the code...?
Example:
from os import popen
try:
popen('echo hi')
doSomethingIllegal;
except:
import logging #Module called only when needed?
logging.exception("Record to logger)
or is this optimized by the compiler the same way as:
from os import popen
import logging #Module will always loaded regardless
try:
popen('echo hi')
doSomethingIllegal;
except:
logging.exception("Record to logger)
This indicates it may make a difference:
"import statements can be executed just about anywhere. It's often useful to place them inside functions to restrict their visibility and/or reduce initial startup time. Although Python's interpreter is optimized to not import the same module multiple times, repeatedly executing an import statement can seriously affect performance in some circumstances."
These two OS questions, local import statements? and import always at top of module? discuss this at length.
Finally, if you are curious about your specific case you could profile/benchmark your two alternatives in your environment.
I prefer to put all of my import statements at the top of the source file, following stylistic conventions and for consistency (also it would make changes easier later w/o having to hunt through the source file looking for import statements scattered throughout)
The general rule of thumb is that imports should be at the top of the file, as that makes code easier to follow, and that makes it easier to figure out what a module will need without having to go through all the code.
The Python style guide covers some basic guidelines for how imports should look: http://www.python.org/dev/peps/pep-0008/#imports
In practice, though, there are times when it makes sense to import from within a particular function. This comes up with imports that would be circular:
# Module 1
from module2 import B
class A(object):
def do_something(self):
my_b = B()
...
# Module 2
from module1 import A
class B(object):
def do_something(self):
my_a = A()
...
That won't work as is, but you could get around the circularity by moving the import:
# Module 1
from module2 import B
class A(object):
def do_something(self):
my_b = B()
...
# Module 2
class B(object):
def do_something(self):
from module1 import A
my_a = A()
...
Ideally, you would design the classes such that this would never come up, and maybe even include them in the same module. In that toy example, having each import the other really doesn't make sense. However, in practice, there are some cases where it makes more sense to include an import for one method within the method itself, rather than throwing everything into the same module, or extracting the method in question out to some other object.
But, unless you have good reason to deviate, I say go with the top-of-the-module convention.
I know there are a bunch of similar questions, but they didn't help me to understand my problem. Also I have 3 modules:
First one is model:
from datetime import datetime
from elixir import *
from run_test import create_db
from sqlalchemy.schema import UniqueConstraint
class ValueTest(Test):
value = Field(Integer)
def __init__(self, name, value):
'''
Constructor
'''
self.name = name;
self.value = value
If I run the test method from the second module named run_test, there aren't any problems
from model import *
def main():
test();
def test():
test = ValueTest("test",2)
if __name__ == "__main__":
main()
But when I try something like that, I get the the well known error NameError: global name 'ValueTest' is not defined
import run_test
def main():
run_test.test()
if __name__ == '__main__':
main()
When you import a module, you don't import the names it has imported; you only import the names it defines itself. You still need to do from model import ValueTest in the last script.
If from foo import * imported every name that foo imported into its own scope, a single import something might also import every symbol in os or sys for example. It would be a nightmare.
Actually, this is not true. The symbols imported from the module are only those defined by the __all__ list set in that module. (If not present, all symbols not starting with _ are indeed imported.)
Thanks Ethan for the correction.
The problem is you have circular imports happening. run_test is importing model, which in turn is importing run_test. Strange things happen when circular imports are used. If you can, put the common functions (create_db, in your example) into another module, then model can import it from there and not from run_test.