改写从导入模块
导入模块的内置功能,我有一个应用程序,我想,当情况发生时替换某些功能,例如:改写从导入模块
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
为主。潘岳:
## 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
“ s print
。我相信检查库可用于此目的,但我无法查找一个示例。
我假设你正在使用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
是不是有两个原因一个好听的名字:,它是不是在所有的描述。一面旗帜仅仅意味着它是True
或False
;它没有说明它的用途。 Python的官方风格指南(PEP 8)推荐使用snake_case,而不使用PascalCase作为常规变量。 PascalCase只能用于类。PEP 8不推荐使用通配符导入(
from <module> import *
),因为它们使命名空间中的名称不清楚,导致读者和自动化工具混淆。 (几乎与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())
感谢您扩大我的评论。尽管如此,我对你建议的sys.stdout的覆盖感到困惑。一旦掌握了一个打印机实例,'printer.write(msg)'不会比'远处的操作'更重要吗?您的建议获得90%的方式,然后使用全球范围确保混淆。 (无论如何+1) – msw
@msw:当然'printer.write(msg)'更清晰,但OP在对他不想'main'的问题的评论中提到。py'知道它的消息正在被重定向。 – zondo
至于全局变量,我不认为这是一个必要的问题。类和函数通常是全局的。全局变量的问题是当它们泄漏到其他名称空间中时。但是,例如,正确导入的'condition_check'将使用'condition_check.printer.use_alternate = False'。我没有看到这个问题。 – zondo
不要有条件覆盖定义过。这似乎是一个聪明的伎俩,但它肯定会破坏事物,或者至少混淆下一个必须查看代码的人(包括你)。如果Flag:MsgBox(message)else:print(message)''好得多。变量名'Flag'也是没有意义的,如果你是Python的新手,忘记了'global',它将会让你陷入困境。 – msw
不幸的是我打算main.py不知道它使用的某些函数被覆盖。 – user1502776