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

自修改Python?如何在不接触sys.stdout的情况下重定向函数中的所有打印语句?,python,python-2.6,Python,Python 2.6,我曾经尝试将一些大型、复杂的python例程移植到线程化环境中 我希望能够在每次调用的基础上,将函数的print语句的输出重定向到其他地方(具体为logging.Logger) 我真的不想修改我正在编译的代码的源代码,因为我需要与调用这些模块的其他软件保持向后兼容性(它是单线程的,只需抓取写入sys.stdout的所有内容即可捕获输出) 我知道最好的选择是重写,但我真的没有选择 编辑- 或者,是否有任何方法可以覆盖打印的本地定义以指向其他函数 然后我可以定义local print=system

我曾经尝试将一些大型、复杂的python例程移植到线程化环境中

我希望能够在每次调用的基础上,将函数的
print
语句的输出重定向到其他地方(具体为
logging.Logger

我真的不想修改我正在编译的代码的源代码,因为我需要与调用这些模块的其他软件保持向后兼容性(它是单线程的,只需抓取写入sys.stdout的所有内容即可捕获输出)

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

编辑-

或者,是否有任何方法可以覆盖打印的本地定义以指向其他函数


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

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

您需要做的是,首先用对执行相同操作的函数的调用替换每个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函数

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

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

from __future__ import print_function
然后您可以将代码更改为使用Python3的
print()
函数

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

例如


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

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

class MyFakeStdout:
    def write(self, s):
        try:
            separate_logs[current_thread()].write(s)
        except KeyError:
            old_stdout.write(s)
然后具有将记录器本地设置为调用的功能(
with


PS:我在标题中看到了“不接触标准输出”,但我认为这是因为你只希望一些线程受到影响。触摸它,同时仍然允许其他线程不受影响地工作,在我看来,这与这个问题是一致的。

为什么不能触摸sys.stdout?我知道,我只是希望避免重大重构。我想这已经是最好的了。有什么方法可以消除对括号的需要吗?哈,这肯定会使netbean的语法检查程序崩溃。@Fake,担心如果这样做,您将不得不使用括号:)我没有想到这一点。嗯。
class MyFakeStdout:
    def write(self, s):
        try:
            separate_logs[current_thread()].write(s)
        except KeyError:
            old_stdout.write(s)