Override function in a module with complex file tree - python

I have a module module containing 2 functions a and b splited into 2 different files m1.py and m2.py.
The module's file tree:
module/
__init__.py
m1.py
m2.py
__init__.py contains:
from .m1 import a
from .m2 import b
m1.py contains:
def a():
print('a')
m2.py contains:
from . import a
def b():
a()
Now, I want to override the function a in a main.py file, such that the function b uses the new function a. I tried the following:
import module
module.a = lambda: print('c')
module.b()
But it doesn't work, module.b() still print a.

I found a solution, that consists in not importing with from . import a but with import module.
m2.py becomes:
import module
def b():
module.a()

Related

Initialize module only once on imports from multiple files

I have multiple python scripts, like this:
utils.py
module1.py
module2.py
module3.py
main.py
...
In utils.py:
import some_lib
role_id = "some_key_1"
secret_id = "some_key_2"
def initialize():
real_key = some_web_request(role_id, secret_id)
some_lib.init(real_key)
# define some other functions using some_lib
In module1.py, module2.py, module3.py:
import utils
# define some other functions using functions in utils.py
In main.py:
import module1
import module2
import module3
# do something
I want to run utils.initialize() only once for initializing some_lib. However, due to how import works in python, if I put initialize() on global area in utils.py then it will run on every import statement run.
I can implement this like this, in utils.py
import some_lib
initialized = False
def initialize():
# same as above
if not initialized:
initialize()
initialized = True
Is this a good practice? Is there better or elegant way to implement this?

Python pass variable to imported module at "compilation" time

I'm trying to create an object from a custom class with a decorator in it.
Then I need to use the decorator of that object to create a bunch of functions in a different file.
I found the solution of using builtins online but it feels a bit hacky and makes my lsp spit out a bunch of errors.
I'm wondering if anyone knows a better solution.
This is my file structure:
main.py
mylib
├── A.py
└── B.py
main.py
import builtins
from mylib.A import A
a = A("This is printing in the decorator")
builtins.FOO = a
import mylib.B as B
B.foo()
B.poo()
A.py
class A:
def __init__(self, _message):
self.message = _message
def our_decorator(self, func):
def function_wrapper():
print(self.message)
func()
return function_wrapper
B.py
import builtins
#builtins.FOO.our_decorator
def foo():
print("foo")
#builtins.FOO.our_decorator
def poo():
print("poo")
I don't want to change the file structure if it can be avoided.
Using builtins to have a magically created decorator is indeed hacky.
An alternative would be to patch the functions in B from main. It is slightly cleaner (and linters should not complain) because the B module has no longer to be aware of the decorator:
main.py:
from mylib.A import A
a = A()
import mylib.B as B
# decorate here the functions of the B module
B.foo = a.our_decorator(B.foo)
B.poo = a.our_decorator(B.poo)
B.foo()
B.poo()
A.py is unchanged...
B.py:
def foo():
print("foo")
def poo():
print("poo")
As only one version of a module exists in a process, you can even use the functions of B from a third module, provided:
either it is imported after the decoration
or it only imports the module name (import mylib.B as B) and not directly the functions (from mylib.B import foo)

Organizing functions into modules based on choice

I have 2 Python modules (e.g. A.py & B.py) that have the same function names (the implementation is different though). A third module (C.py) has a function that requires the functions in A or B, depending on user choice.
A fourth module (D.py) will import either A or B, and then C.
How do I correctly setup the modules and imports?
# module A.py
def write():
print('A')
# module B.py
def write():
print('B')
# module C.py
def foo():
write()
# module D.py (main executed module)
if choiceA:
import A
import C
else:
import B
import C
C.foo()
This is essentially a basic case of a Strategy Pattern. Instead of doing a double-import and implicitly expecting module C to get the right module, you should just explicitly pass the appropriate selection for it to call.
Using modules A and B as before:
# module C.py
def foo(writer):
writer.write()
# module D.py
import A
import B
import C
if choiceA:
my_writer = A
elif choiceB:
my_writer = B
C.foo(my_writer)
This will also continue to work exactly the same way if you choose to define A, B, and C as a class hierarchy instead of modules.
Not much really.
Module A.py:
def write():
print('A')
Module B.py
def write():
print('B')
Module C.py
def foo(choice):
if choice == 'A':
import A
A.write()
elif choice == 'b':
import B
B.write()
else:
#whatever
module D.py
choice = input('Enter choice: ')
import C
C.foo(choice)

How to change and save variable in different files

I have three python files:
a.py
theVariable = "Hello!"
b.py
import a
a.theVariable = "Change"
c.py
import a
while True:
print(a.theVariable)
I want c.py to print out "Change" instead of "Hello!". How can I do this and why wont this work?
There needs to be separate files because b.py would be running a Tkinter gui.
You can use classes to get an instance variable which holds some state
a.py
class Foo():
def __init__(self):
self.greeting = "Hello"
And create functions so that you can defer actions on references
b.py
def changer(f):
f.greeting = "Change"
When you import a class and then pass it to a function, you are passing a reference to something that can change state
c.py
from a import Foo
from b import changer
a = Foo()
for x in range(10): # simple example
if x > 5:
changer(a)
print(a.greeting)
a.py
theVariable = "Hello!"
def change(variable):
theVariable = variable
b.py
import a
change('change')
c.py
import a
while True:
print(theVariable)
i've been working with PyQt recently and this worked fine. setting a function in the orgin .py file makes it much simpler.

Calling class in another folder

Given the folder structure as follows:
folder1
__init.py__
python1.py
folder2
__init.py__
class1.py
say in class1.py I have
class aa:
def __init__(self,max):
self.max=max
def hello(self):
print(self.max)
What should I import from python1.py to invoke aa.hello()?
i.e., in python1.py
#what do I need to import here
myaa=aa(100)
myaa.hello()
Answer my own:
from folder2.class1 import aa

Categories

Resources