改写从导入模块

改写从导入模块

问题描述:

导入模块的内置功能,我有一个应用程序,我想,当情况发生时替换某些功能,例如:改写从导入模块

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。我相信检查库可用于此目的,但我无法查找一个示例。

+1

不要有条件覆盖定义过。这似乎是一个聪明的伎俩,但它肯定会破坏事物,或者至少混淆下一个必须查看代码的人(包括你)。如果Flag:MsgBox(message)else:print(message)''好得多。变量名'Flag'也是没有意义的,如果你是Python的新手,忘记了'global',它将会让你陷入困境。 – msw

+0

不幸的是我打算main.py不知道它使用的某些函数被覆盖。 – user1502776

我假设你正在使用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 

我会注意,但是,有两件事情:

  1. Flag是不是有两个原因一个好听的名字:,它是不是在所有的描述。一面旗帜仅仅意味着它是TrueFalse;它没有说明它的用途。 Python的官方风格指南(PEP 8)推荐使用snake_case,而不使用PascalCase作为常规变量。 PascalCase只能用于类。

  2. PEP 8不推荐使用通配符导入(from <module> import *),因为它们使命名空间中的名称不清楚,导致读者和自动化工具混淆。 (几乎与Imports一节中的确切引用相同。)

  3. 您不需要覆盖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添加新行的轻微的缺点,但一个随时可以使用的东西的alternatelambda msg: MsgBox(msg.strip())

+0

感谢您扩大我的评论。尽管如此,我对你建议的sys.stdout的覆盖感到困惑。一旦掌握了一个打印机实例,'printer.write(msg)'不会比'远处的操作'更重要吗?您的建议获得90%的方式,然后使用全球范围确保混淆。 (无论如何+1) – msw

+1

@msw:当然'printer.write(msg)'更清晰,但OP在对他不想'main'的问题的评论中提到。py'知道它的消息正在被重定向。 – zondo

+0

至于全局变量,我不认为这是一个必要的问题。类和函数通常是全局的。全局变量的问题是当它们泄漏到其他名称空间中时。但是,例如,正确导入的'condition_check'将使用'condition_check.printer.use_alternate = False'。我没有看到这个问题。 – zondo