编辑:因为似乎没有解决方案,或者我正在做一些没人知道的非标准的东西 - 我会修改我的问题也要问:当python应用程序创建时,完成日志记录的最佳方法是什么很多系统调用?
我的应用程序有两种模式.在交互模式下,我希望所有输出都转到屏幕以及日志文件,包括来自任何系统调用的输出.在守护程序模式下,所有输出都将转到日志中.守护进程模式很好用os.dup2().我无法找到一种方法将所有输出"发送"到交互模式的日志,而无需修改每个系统调用.
换句话说,我想要命令行'tee'的功能,用于python应用程序生成的任何输出,包括系统调用输出.
澄清:
要重定向所有输出,我会做这样的事情,并且效果很好:
# open our log file
so = se = open("%s.log" % self.name, 'w', 0)
# re-open stdout without buffering
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
# redirect stdout and stderr to the log file opened above
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
Run Code Online (Sandbox Code Playgroud)
关于这一点的好处是它不需要来自其余代码的特殊打印调用.该代码还运行一些shell命令,因此不必单独处理每个输出.
简单地说,我想做同样的事情,除了重复而不是重定向.
起初以为我认为简单地扭转它们dup2应该有效.为什么不呢?这是我的测试:
import os, sys
### my broken solution:
so = se = open("a.log", 'w', 0)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
os.dup2(sys.stdout.fileno(), so.fileno())
os.dup2(sys.stderr.fileno(), se.fileno()) …Run Code Online (Sandbox Code Playgroud) 我有一个Python脚本,它使用'Print'打印到stdout.我最近通过Python Logger添加了日志记录,并希望如果启用了日志记录,这些打印语句将转到logger.我不想修改或删除这些打印语句.
我可以通过'log.info("some info msg")'来记录.我希望能够做到这样的事情:
if logging_enabled:
sys.stdout=log.info
print("test")
Run Code Online (Sandbox Code Playgroud)
如果启用了日志记录,则应记录"test",就像我执行log.info("test")一样.如果未启用日志记录,则只应将"test"打印到屏幕上.
这可能吗?我知道我可以以类似的方式将stdout指向文件(请参阅:重定向打印到日志文件)
我有一个相当不寻常的要求,我想......在我解释之后,我会解释为什么.
什么
我想检测我的对象何时被写入stdout,以便我可以在那时执行副作用.所以,例如,当我键入:
sys.stdout.write(instance_of_my_class)
Run Code Online (Sandbox Code Playgroud)
它应该执行副作用.我做了我的课堂上的一个子类str和压倒__call__,__unicode__,__str__,__repr__,index,decode,encode,format,__format__,__getattribute__,__getitem__,并__len__让他们每个人打印一份声明中表示,他们已经被调用,但似乎sys.stdout.write为了调用这些都不打印一个对象.
请注意,我是专门讨论sys.stdout.write而不是,例如,print- 我已经发现无论给出什么,都会print调用__str__它.
为什么
这个问题继续从Windows中的彩色Python提示的答案?离开了.
我发现,每次蟒蛇需要显示交互式提示,它调用__str__上sys.ps1和sys.ps2,然后将其保存在命令行上显示的结果.这意味着任何副作用sys.ps2.__str__都是在它们之后引起的sys.ps1.__str__,但是我希望让它们等到显示时间sys.ps2.
因此,我一直在返回我的子类,而不是返回一个strin sys.ps2.__str__,我str希望以某种方式能够捕获sys.stdout.write它的时候.
我试图了解如何创建自定义打印功能.(使用python 2.7)
import sys
class CustomPrint():
def __init__(self):
self.old_stdout=sys.stdout #save stdout
def write(self, text):
sys.stdout = self.old_stdout #restore normal stdout and print
print 'custom Print--->' + text
sys.stdout= self # make stdout use CustomPrint on next 'print'
# this is the line that trigers the problem
# how to avoid this??
myPrint = CustomPrint()
sys.stdout = myPrint
print 'why you make 2 lines??...'
Run Code Online (Sandbox Code Playgroud)
上面的代码将此打印到控制台:
>>>
custom Print--->why you make 2 lines??...
custom Print--->
>>>
Run Code Online (Sandbox Code Playgroud)
我想只打印一行:
>>>
1custom Print--->why you make …Run Code Online (Sandbox Code Playgroud) 我想修补Python列表,特别是__setitem__用自定义代码替换方法.请注意,我不是要扩展,而是覆盖内置类型.例如:
>>> # Monkey Patch
... # Replace list.__setitem__ with a Noop
...
>>> myList = [1,2,3,4,5]
>>> myList[0] = "Nope"
>>> myList
[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)
是的,我知道这对python代码来说是一个彻头彻尾的变态.不,我的用例并没有多大意义.尽管如此,它能做到吗?
forbiddenfruit模块允许修补C内置,但在尝试覆盖列表方法时不起作用我实际上设法覆盖了方法本身,如下所示:
import ctypes
def magic_get_dict(o):
# find address of dict whose offset is stored in the type
dict_addr = id(o) + type(o).__dictoffset__
# retrieve the dict object itself
dict_ptr …Run Code Online (Sandbox Code Playgroud) 考虑这个例子,其中__dict__类的所有实例的 都A将指向全局 dict shared。
shared = {'a': 1, 'b': 2}
class A(object):
def __init__(self):
self.__dict__ = shared
Run Code Online (Sandbox Code Playgroud)
现在让我们测试一些事情:
>>> a = A()
>>> b = A()
>>> a.a, a.b, b.a, b.b
(1, 2, 1, 2)
>>> b.x = 100
>>> shared
{'a': 1, 'x': 100, 'b': 2}
>>> a.x
100
>>> c = A()
>>> c.a, c.b, c.x
(1, 2, 100)
>>> shared['foo'] = 'bar'
>>> a.foo, b.foo, c.foo
('bar', 'bar', 'bar')
>>> a.__dict__, b.__dict__, …Run Code Online (Sandbox Code Playgroud)