自修改Python?如何在不触及sys.stdout的情况下重定向函数中的所有print语句?

时间:2011-01-01 10:04:11

标签: python python-2.6

我遇到的情况是我试图将一些大而复杂的python例程移植到线程环境中。

我希望能够在每个调用的基础上将函数的print语句的输出重定向到其他地方(logging.Logger是特定的)。

我真的不想修改我正在编译的代码的源代码,因为我需要保持与调用这些模块的其他软件的向后兼容性(这是单线程的,并通过简单地抓取写入{的所有内容来捕获输出{1}})。

我知道最好的选择是做一些重写,但我真的没有选择。

修改 -

或者,有什么方法可以覆盖print的本地定义以指向不同的函数?

然后我可以定义本地print = system print,除非被kwarg覆盖,并且只涉及在每个例程的开头修改几行。

3 个答案:

答案 0 :(得分:6)

在Python2.6(和2.7)中,您可以使用

from __future__ import print_function

然后您可以像使用Python3一样更改代码以使用print()函数

这允许您创建一个名为print的模块全局或本地函数,它将优先于内置函数使用

例如

from __future__ import print_function

def f(x, print=print):
    print(x*x)

f(5)
L=[]
f(6, print=L.append)
print(L)

答案 1 :(得分:3)

修改源代码不一定意味着破坏向后兼容性。

您需要做的是首先通过调用执行相同操作的函数来替换每个print语句:

import sys
def _print(*args, **kw):
    sep = kw.get('sep', ' ')
    end = kw.get('end', '\n')
    file = kw.get('file', sys.stdout)
    file.write(sep.join(args))
    file.write(end)

def foo():
   # print "whatever","you","want"
   _print("whatever","you","want")

然后第二步是直接停止使用_print函数并使其成为关键字参数:

def foo(_print=_print):
    ...

并确保更改所有内部函数调用以传递_print函数。

现在所有现有代码都将继续工作并将使用print,但您可以传入任何您想要的_print函数。

请注意,_print的签名与更新版本的Python中的print函数完全相同,因此只要您升级,就可以将其更改为使用print()。此外,您可以使用2to3来迁移现有代码中的print语句,这将减少所需的编辑。

答案 2 :(得分:2)

六十年代的某个人对如何解决这个问题有了一个想法,但它需要一些外星技术。不幸的是,python没有“当前环境”概念,这意味着除非在调用中将其指定为参数,否则无法提供上下文。

为了处理这个特定的问题,将stdout替换为一个类似于文件的对象,该对象的行为取决于特定于线程的上下文?这样源代码保持不变,但是例如,您可以为每个线程获取单独的日志。在特定的每次呼叫方式上执行此操作甚至更容易......例如:

class MyFakeStdout:
    def write(self, s):
        try:
            separate_logs[current_thread()].write(s)
        except KeyError:
            old_stdout.write(s)

然后具有将记录器本地设置为调用(with

的功能 PS:我在标题中看到了“没有触摸stdout”,但我认为这是因为你只想要一些线程受到影响。触摸它同时仍允许其他线程不受影响似乎与我的问题兼容。