Reputation: 562
I have an application where I would like to override certain functions when a condition occurs, for example:
condition_check.py:
Flag = True
import ctypes # An included library with Python install.
import inspect
def MsgBox(msg):
ctypes.windll.user32.MessageBoxA(0, msg, 'MsgBox', 1)
def check():
global print
if Flag:
def print(msg):
MsgBox(msg)
else:
pass
main.py:
## works
from condition_check import *
MsgBox('this is msgbox')
print('this is a print')
## does not work
import condition_check
condition_check.MsgBox('this is msgbox')
print('this is a print')
I understand that the condition_check.py
is overriding its own print
instead of the main.py
's print
. I believe inspect library could be used for this purpose but I am not able to lookup an example.
Upvotes: 3
Views: 1796
Reputation: 20336
I am assuming that you are using Python 3. If you are, you need merely set an attribute of the built-in module.
import builtins
import ctypes
original = builtins.print
Flag = True
def MsgBox(msg):
ctypes.windll.user32.MessageBoxA(0, msg, 'MsgBox', 1)
def check():
if Flag:
builtins.print = MsgBox
else:
builtins.print = original
I will note, however, a couple things:
Flag
is not a good name for two reasons: 1, it isn't at all descriptive. A flag merely means that it is True
or False
; it doesn't say anything about what it is for. 2, the official style guide for Python (PEP 8) recommends snake_case, not PascalCase for regular variables. PascalCase should be used only for classes.
Wildcard imports (from <module> import *
) are not recommended by PEP 8 because they make it unclear which names are present in the namespace, confusing both readers and automated tools. (Almost an exact quotation from the section on Imports.)
You don't need to override the print
function. A better way is to override sys.stdout
to a stream that controls where it goes:
import ctypes
import sys
def MsgBox(msg):
ctypes.windll.user32.MessageBoxA(0, msg, 'MsgBox', 1)
class Printer:
def __init__(self, original, alternate, use_alternate):
self.original = original
self.alternate = alternate
self.use_alternate = use_alternate
def write(self, msg):
if self.use_alternate:
return self.alternate(msg)
return self.original(msg)
sys.stdout = printer = Printer(sys.stdout.write, MsgBox, True)
Your flag is then printer.use_alternate
. Besides being much easier to control, this is also compatible with Python 2, even though the Python 2 print
is a statement. This does have the slight disadvantage of keeping the newline that print
adds, but one can always use an alternate
of something like lambda msg: MsgBox(msg.strip())
Upvotes: 2