我遇到的情况是我试图将一些大而复杂的python例程移植到线程环境中。
我希望能够在每个调用的基础上将函数的print
语句的输出重定向到其他地方(logging.Logger
是特定的)。
我真的不想修改我正在编译的代码的源代码,因为我需要保持与调用这些模块的其他软件的向后兼容性(这是单线程的,并通过简单地抓取写入{的所有内容来捕获输出{1}})。
我知道最好的选择是做一些重写,但我真的没有选择。
修改 -
或者,有什么方法可以覆盖print的本地定义以指向不同的函数?
然后我可以定义本地print = system print,除非被kwarg覆盖,并且只涉及在每个例程的开头修改几行。
答案 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
)