如何“过载” Python的打印功能“全局”?(How to “overload” python&#

2019-08-04 02:19发布

我使用的Python 2.6.6,我需要重载默认的蟒纹功能。 我需要做的,因为此代码的系统,其中内置的功能已被用来生成输出上使用,否则没有任何输出。

所以,仅仅举例来说,如果你有一个python脚本是这样的:

from __future__ import print_function

def NewPrint(Str):
    with open("somefile.txt","a") as AFile:
        AFile.write(Str)

def OverloadPrint():
    global print
    print = NewPrint

OverloadPrint()
print("ha")

它工作正常。 输入到“超载”打印是NewPrint指定的文件中。

现在,考虑到这一点,我想能够运行的几行以上,并具有打印做脚本的整个执行过程中NewPrint做什么。 现在,如果我从另一个调用模块使用打印功能,将使用内置的打印,而不是一个我刚刚改写。 我想这已经是与命名空间和内置插件,但我的蟒蛇是不够好。

编辑:

我试图保持简单,但看起来像这样造成更多的混乱......

  1. 该重载打印将打印到一个GUI的功能,所以无需关心重定向如果函数过载。
  2. 我知道我的例子并没有做什么的打印功能实际执行。 的,我怎么想的编码它是一个更好的例子(仍然不是很大,我知道):

     def hli_print(*args, **kw): """ print([object, ...], sep=' ', end='\n', file=sys.stdout) """ sep = kw.get('sep', ' ') end = kw.get('end', '\n') File = kw.get('file', sys.stdout) args = [str(arg) for arg in args] string = sep.join(args) + end File.write(string) hli_Print(string) 
  3. 从2上面可以看到我不得不使用打印到GUI“hli_Print”的功能,它是一个C ++函数通过了一大口包装暴露。

  4. 我们只使用标准库和我们自己痛饮的包装,也是我们的开发人员使用打印的功能(习惯3.X)。 所以,我真的不担心很多关于其他模块调用打印,并具有别的东西来代替。

从所有的意见,我想这只是使用一些print_()函数,而不是打印()(这是我们目前正在做的)可能是最好的,但我真的很好奇,看看是否在蟒蛇有可能做什么我描述。

Answer 1:

我不认为你的问题使任何意义。

首先,如果你正在运行的Python 2.6,一切导入等,将使用print语句,即使你自己的模块使用print功能。 因此,重载函数不会影响任何东西。

其次,你说“我需要做的,因为此代码的系统,其中内置的功能已被用来生成输出上使用,否则没有任何输出。” 那么,你的NewPrint不是一个内置的功能,所以这无论如何也不会帮助。

另外值得一提的是,你的NewPrint没有实现大部分的功能print功能,甚至认为它确实实现了位,但它确实错( print(s)将打印s 跟着一个换行符 )。 所以,如果你没有更换内置print与你的功能,你只是最终破坏最自己的代码和任何你依赖STDLIB /第三方代码。

这可能是你可以完成你通过创建一个类文件对象,取代想要什么sys.stdout 。 否则,我看不出任何东西可以工作。 例如:

class FakeStdOut(object):
    # … lots of other stuff to implement or inherit
    def write(s):
        with open("somefile.txt", "a") as f:
            f.write(s)

def OverloadPrint():
    sys.stdout = FakeStdOut()

但即使这样的作品,它可能不是你真正想要的。 对于一个快速和肮脏的脚本,有缺陷的外壳在一个平台上,这有时是一个方便的想法。 但除此之外,它可能会导致你从长远来看,更多的麻烦比想出一个更好的解决方案。 这里只是几件事情,可以去错了(只是作为例子,而不是一个详尽的列表)

  • 如果你想改变输出去的文件,你必须修改剧本。 如果用来代替>>在外壳,你可以只调用脚本不同。
  • 有人阅读或调试代码(如,说,你,你忘了三个月后它是如何工作)会发生的事情感到惊讶。
  • 有些STDLIB /第三方/同事/等。 代码调用将检查stdout是一个tty你做出改变之前,对自己进行配置的交互输出。
  • 一些代码将打印你有机会重新定向之前,你会花几个小时试图找出如何重新安排事情解决该问题。
  • 你必须知道如何实现“类文件对象”完全和这一概念没有完全定义2.6或者它将与一些代码打破。
  • 冥冥之中,有你以为是一些代码print ING,但它实际上是,比如说, log更改或写入sys.stderr或做别的东西,所以你给自己的安全,你现在登录的一切虚假的安全感在somefile.txt ,否则不会发现直到第6个月后,当你迫切需要失踪信息,在客户现场调试问题。

既然你编辑的问题,这里的一些进一步的反应:

从所有的评论我想这只是使用一些print_()函数,而不是打印的()

是的,这是一个更合理的选择。 但我可能不会把它print_ 。 而且它更简单把“做或不做”逻辑里​​面的功能,而不是进出全局名称(特别是因为你要拧,最多在某个时刻的交换实现,如果你的代码是不是都在一个大模块)。

我曾在一个类似用途的情况下,一个项目:我们有我们想去的系统日志,也去GUI“登录窗口”,如果它是打开的邮件。 因此,我们写了一个glog功能包,最多,没有人抱怨说,他们想写print代替。 (事实上,在球队至少一个家伙很是高兴,他可以使用print快速和肮脏的打印输出在调试时不影响实际产出,尤其是当他不得不调试GUI日志代码。)

但是,这只是因为我们没有与新的(当时)的经验logging组件。 现在,我想我会创建一个logging Handler实现,写入GUI窗口,只需添加该处理程序,并使用标准的logging比比皆是方法。 这听起来像这可能是你最好的选择。

此外,最后一个可能是无关的枝节问题:

我们只使用标准库和我们自己痛饮的包装,也是我们的开发人员使用打印的功能(习惯3.X)。

那么,为什么不首先使用3.x的? 显然3.X有实际3.x的标准库,而不是什么样的接近3.x的标准库,如果你做一些__future__语句,SWIG可与3.X ...



Answer 2:

作为@ abarnert的答案和一些评论人士指出,更换print可能不是一个好主意。 但只是为了完整起见,这里就是为什么你的代码没有成功覆盖它的其他模块。

print功能在模块定义__builtin__ (其被重命名为builtins在Python 3)。 Python解释器,使一切都在__builtin__模块的名称空间提供给它运行的所有其他代码,而无需将它导入到你的模块的自己的命名空间。 它的神奇!

然而,当你创建自己的函数命名print (使用print = NewPrint )它不会覆盖在原来的版本__builtin__ 。 你只是建立在你的模块命名空间的影子旧的一个新的变量__builtin__ 。 在global语句不帮助,因为它只是让你告诉Python要写入你的模块的全局命名空间,而不是一个函数内的一些内部命名空间。

要替换默认的print功能,您将需要明确取代它在__builtin__模块。 下面是确实是一些示例代码:

from __future__ import print_function
try:
    import __builtin__ as builtins # Python 2
except ImportError:
    import builtins # Python 3

_print = print # keep a local copy of the original print
builtins.print = lambda *args, **kwargs: _print("foo:", *args, **kwargs)

要重复,这实在不是一个好主意。 同时确保我明白我在这个答案在谈论,我设法通过更换崩溃我的Python会议的一个print与没有接受lambda函数file是Python使用打印到标准错误参数。 几行后,异常处理程序并不高兴,当它得到了第二个例外,同时尝试打印另一个异常的回溯。

几乎可以肯定有更好的方式得到你想要的结果。



文章来源: How to “overload” python's print function “globally”?