从导入的模块覆盖导入模块的内置函数
Override importing module's built-in functions from imported module
我有一个应用程序,我想在某个情况发生时覆盖某些功能,例如:
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')
我知道 condition_check.py
正在覆盖它自己的 print
而不是 main.py
的 print
。我相信 inspect 库可用于此目的,但我无法查找示例。
我假设你使用的是Python 3.如果你是,你只需要设置内置模块的一个属性。
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
不过,我要注意几件事:
Flag
不是一个好名字有两个原因:1,它根本不是描述性的。标志仅表示它是 True
或 False
;它没有说明它的用途。 2,Python (PEP 8) 的官方风格指南推荐 snake_case,而不是常规变量的 PascalCase。 PascalCase 应该只用于 类.
通配符导入 (from <module> import *
) 不被 PEP 8 推荐,因为它们使命名空间中存在哪些名称变得不清楚,混淆了读者和自动化工具。 (几乎完全引用了 Imports 的部分。)
您不需要覆盖 print
函数。更好的方法是将 sys.stdout
覆盖为控制其去向的流:
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)
你的旗帜是 printer.use_alternate
。除了更容易控制之外,这也与 Python 2 兼容,即使 Python 2 print
是一个语句。这确实有保留 print
添加的换行符的轻微缺点,但是人们总是可以使用 alternate
之类的 lambda msg: MsgBox(msg.strip())
我有一个应用程序,我想在某个情况发生时覆盖某些功能,例如:
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')
我知道 condition_check.py
正在覆盖它自己的 print
而不是 main.py
的 print
。我相信 inspect 库可用于此目的,但我无法查找示例。
我假设你使用的是Python 3.如果你是,你只需要设置内置模块的一个属性。
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
不过,我要注意几件事:
Flag
不是一个好名字有两个原因:1,它根本不是描述性的。标志仅表示它是True
或False
;它没有说明它的用途。 2,Python (PEP 8) 的官方风格指南推荐 snake_case,而不是常规变量的 PascalCase。 PascalCase 应该只用于 类.通配符导入 (
from <module> import *
) 不被 PEP 8 推荐,因为它们使命名空间中存在哪些名称变得不清楚,混淆了读者和自动化工具。 (几乎完全引用了 Imports 的部分。)您不需要覆盖
print
函数。更好的方法是将sys.stdout
覆盖为控制其去向的流: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)
你的旗帜是
printer.use_alternate
。除了更容易控制之外,这也与 Python 2 兼容,即使 Python 2print
是一个语句。这确实有保留print
添加的换行符的轻微缺点,但是人们总是可以使用alternate
之类的lambda msg: MsgBox(msg.strip())