gpt4 book ai didi

Python - 检测我的对象何时写入标准输出?

转载 作者:太空狗 更新时间:2023-10-29 18:34:15 26 4
gpt4 key购买 nike

我有一个相当不寻常的请求,我想......我会先解释为什么再解释是什么。

什么

我想检测何时将我的对象写入标准输出,以便我可以在那时执行副作用。因此,例如,当我键入:

sys.stdout.write(instance_of_my_class)

它应该有副作用。我让我的类成为 str 的子类并覆盖 __call____unicode____str__ __repr__, index, decode, encode, format, __format__ , __getattribute__, __getitem__, 和 __len__ 这样他们每个人都会打印一条声明,表明他们已经被调用,但似乎 sys.stdout.write 不调用任何一个来打印对象。

请注意,我专门谈论 sys.stdout.write 而不是,例如 print - 我发现 print无论给定什么,都会调用 __str__

为什么

这个问题从 Colored Python Prompt in Windows? 的答案开始继续离开了。

我发现python每次需要显示交互提示时,都会调用sys.ps1sys.ps2上的__str__,然后它保存要在命令行上显示的结果。这意味着 sys.ps2.__str__ 中的任何副作用都是在 sys.ps1.__str__ 中的副作用之后引起的,但我想让它们等到显示的时候sys.ps2.

因此,我没有在 sys.ps2.__str__ 中返回 str,而是返回了我的 str 子类,我我希望在调用 sys.stdout.write 时能够以某种方式捕获。

最佳答案

有趣的问题!我的第一个猜测是 sys.stdout.write 没有调用 __str__ 方法,因为你的对象已经一个 str(或者至少是它的一个子类,这对于所有意图和目的来说已经足够好了)...所以不需要转换方法。

进一步的调查表明 sys.stdout.write 真的不想调用 __str__ 方法......

子类方法

稍微反省一下,您可以找出str 子类的哪些方法sys.stdout.write 调用(答案是,不多):

class superstring(str):
def __getattribute__(self, name):
print "*** lookup attribute %s of %s" % (name, repr(self))
return str.__getattribute__(self, name)

foo = superstring("UberL33tPrompt> ")
sys.stdout.write(foo)

在 Unicode 环境(Python 2.7、iPython notebook)中运行,打印:

*** lookup attribute __class__ of 'UberL33tPrompt> '
*** lookup attribute decode of 'UberL33tPrompt> '
UberL33tPrompt>

这看起来有点笨拙,但您可以覆盖子类的 decode 方法来执行所需的副作用。

但是,在非 Unicode 环境中没有属性查找

包装方法

与其使用 str 的子类,也许您需要的是围绕 str 的某种“包装器”。这是一个丑陋的探索性 hack,它创建了一个将其大部分属性委托(delegate)给 str 的类,但它严格来说并不是其子类:

class definitely_not_a_string(object):
def __init__(self, s):
self.s = s
def __str__(self):
print "*** Someone wants to see my underlying string object!"
return self.s
def decode(self, encoding, whatever):
print "*** Someone wants to decode me!"
return self.s.decode(encoding, whatever)
def __getattribute__(self, name):
print "*** lookup attribute %s of %s" % (name, repr(self))
if name in ('s', '__init__', '__str__', 'decode', '__class__'):
return object.__getattribute__(self, name)
else:
return str.__getattribute__(self, name)

foo = definitely_not_a_string("UberL33tPrompt> ")
sys.stdout.write(foo)

在 Unicode 环境中,这给出了基本相同的结果:

*** lookup attribute __class__ of <__main__.definitely_not_a_string object at 0x00000000072D79B0>
*** lookup attribute decode of <__main__.definitely_not_a_string object at 0x00000000072D79B0>
*** Someone wants to decode me!
*** lookup attribute s of <__main__.definitely_not_a_string object at 0x00000000072D79B0>
UberL33tPrompt>

但是,当我在非Unicode环境下运行时,definitely_not_a_string给出了错误信息:

TypeError: expected a character buffer object

... 这表明 .write 方法直接进入 C 级 buffer interface当它不需要做任何 Unicode 解码时。

我的结论

在 Unicode 环境中,覆盖 decode 方法似乎是一个可能的错误,因为 sys.stdout.write 在它执行时调用此方法需要将 str 解码为 Unicode。

但是,在非 Unicode 环境中,.write 似乎没有进行任何属性查找,而是直接进入 C 级字符缓冲区协议(protocol),因此无法拦截它从 Python 代码访问。事实上,help(sys.stdout.write) 验证它是一个内置函数(也就是用 C 语言而不是 Python 编写的)。

关于Python - 检测我的对象何时写入标准输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24313972/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com