Python: importing another .py file - python

I have a class and I want to import a def function by doing:
import <file>
but when I try to call it, it says that the def can not be found. I also tried:
from <file> import <def>
but then it says global name 'x' is not defined.
So how can I do this?
Edit:
Here is a example of what I am trying to do. In file1.py I have:
var = "hi"
class a:
def __init__(self):
self.b()
import file2
a()
and in file2.py I have:
def b(self):
print(var)
it is just giving me a error though.

import file2
loads the module file2 and binds it to the name file2 in the current namespace. b from file2 is available as file2.b, not b, so it isn't recognized as a method. You could fix it with
from file2 import b
which would load the module and assign the b function from that module to the name b. I wouldn't recommend it, though. Import file2 at top level and define a method that delegates to file2.b, or define a mixin superclass you can inherit from if you frequently need to use the same methods in unrelated classes. Importing a function to use it as a method is confusing, and it breaks if the function you're trying to use is implemented in C.

Related

Instances interacting cause circular import error

I have instances of a class that depend on each other and are defined in separate scripts.
my_class.py
class MyClass:
def __init__(self):
self.value = None
scriptA.py
import scriptB
from my_class import MyClass
foo = MyClass()
foo.value = scriptB.bar.value + 1
scriptB.py
import scriptA
from my_class import MyClass
bar = MyClass()
bar.value = 2
baz = MyClass()
baz.value = scriptA.foo.value + 1
scriptC.py
import scriptA
import scriptB
print(scriptA.foo.value + scriptB.bar.value + scriptB.baz.value)
I'm sourcing scriptC. I would expect for Python to calculate:
scriptA.foo = 3
scriptB.bar = 2
scriptB.baz = 4
Reality:
[...]
baz.value = scriptA.foo.value + 1
AttributeError: partially initialized module 'scriptA' has no attribute 'foo' (most likely due to a circular import)
I do understand why it happens. The question is what is the structure that Python expects?
This happens because of circular imports. You see you are importing scriptB into scriptA but in scriptB it requires scriptA as a module to run. Try not importing scriptA and taking the required values of scriptA as a function parameter and run it as per your usage in the script.
scriptB
def foo(var):
# lets say you wanna print var
print(var)
scriptA
import scriptB
scriptB.foo()
Let me explain.
I just meant for example, you want an variable from scriptA which is required in scriptB. So, instead of importing scriptA you make an function def foo(var). Now you wanna do stuff with that var so you do stuff with the var in the foo function or you can just store the value in another empty existing variable in scriptB. Now you import this foo function in scriptA. There you pass the variable you were importing earlier in this function. It will do the same thing. Instead you have to just call the function.
You do this instead of this
Having a variable called var in scriptA and trying to import it in scriptB and print. This will cause circular import as you are importing scriptA in scriptB and scriptB in scriptA.
So, for structuring
Always make a function with a parameter which you will suppose as the imported variable from the first script and do stuff in these type of problems. Like you need a's stuff in b and your import a in b and b in a. This wouldn't work. You make a function and have a parameter there which acts as the variable your importing. Then you call that function in the first script and it should work good if you did things correctly inside of that functions.

How to initialize whole Python module and import all classes without needing to reference module name for every call?

Suppose I have a module named 'module1', which has many classes. I want to use all of their classes in my main controller main.py . I can import whole module with import module1, however, I assume that the class names in 'module1' are unique and I do not want to reference module1 every time I call its function such as module1.class1().
How can I import the whole contents of a module without explicitly having to state class/function names and still being able to refer to them without stating the module name.
Such as:
# module1.py.
class Class1():
pass
class Class2():
pass
# __main__.py
import module1
# The following will not work.
object1 = Class1()
object2 = Class2()
You can use the * import pattern
from module1 import *
This lets you use everything inside that module without referencing it.
from module1 import *
instance = Class1()
However, this is generally discouraged. For reasons why, some additional reading:
Why is "import *" bad?
https://www.geeksforgeeks.org/why-import-star-in-python-is-a-bad-idea/

Updating an Imported Object

Suppose file_A.py is written as so:
#file_A.py
my_object = create_new_object()
def update_object():
global my_object
my_object = update(my_object)
and then in file_B.py we do as so:
#file_B.py
from file_A import my_object, update_object
def process_object(object):
#do some operation ...
process_object(my_object) #first call to process_object()
update_object()
process_object(my_object) #second call to process_object()
My question is, when the second call to process_object() is made, will it use the original version of my_object ,which is imported at the top of file_B.py, be used, or will it use the updated version which replaces my_object when the update_object() function is called from file_B.py?
Variables are passed by reference. In file_A you will update the modules reference to my_object but the value imported in file_B will still have the old reference. For example:
Say I have file testA.py
a = 1
def foo():
global a
a = 2
And testB.py
from testA import a, foo
print(a)
foo()
print(a)
If I run testB.py you will get the output 1,1
This is because the global only updated the reference attached to the module testA.py. If you were to access the module however, then you would see it did update there. An example where you access the module instead
testC.py
import testA
print(testA.a)
testA.foo()
print(testA.a)
This will output 1, 2
Note that the same variable (even if global) can have different values in different python modules. Thus the best way to reference a variable from another module is by using module.variable
So your code might look like
import file_A
print(file_A.my_object)
file_A.process_object(file_A.my_object)
file_A.process_object(file_A.my_object)
print(file_A.my_object)
The key to referencing the right variable is to use the module name.
This can also be useful when you are working with multiple files and you need to keep some global variables.

Python - Importing module gets global variables

I have two Python scripts, one testclass.py:
import numpy
zz = numpy
class Something(object):
def __init__(self):
self.xp = zz
and one testscript.py:
from testclass import Something
x = Something()
print(x.xp)
I expected testscript.py to throw an error because I thought that testscript only imports the class Something (with its __init__ method), and not the global variable zz. So, given this bevahiour, my question is, when importing from a module, does Python "run" everything in the module file?
Yes. When you execute:
from testclass import Something
It has the same effect as:
import testclass
Something = testclass.Something
More generally, the Python interpreter can't know beforehand what objects your module exposes (unless you explicitly name them in __all__). For an extreme case, consider the following:
a.py:
import random
if random.random() > 0.5:
class Foo(object):
pass
else:
class Bar(object):
pass
Running from a import Foo has a 50% chance of failing because the a module object may or may not have a Foo attribute.

python import nested class

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

Categories