我正在制作一个具有不同控制流的程序,具体取决于是否已将任何内容写入sys.stdout
。我首先在Mac上制作了该程序,然后可以做到
pos = sys.stdout.tell()
exec(some_code, globals)
if pos == sys.stdout.tell():
# ...
但是事实证明,我无法在Linux上使用tell()
方法,这对我来说是个问题。在这种情况下,如何判断sys.stdout
是否被触摸?
我认为我可以想到的是为sys.stdout
和sys.stdout.buffer
都创建一个包装器类,以监视所有书写调用,尽管我不确定这样做是否可靠。
或者我想我可以尝试contextlib.redirect_stdout
。但是我不确定如何使用它。.
编辑:
我正在使用此实用程序https://github.com/bombs-kim/pythonp。我要实现的功能是在没有输出到stdout的情况下自动将some_code
中exec(some_code, globals)
的最后一个表达式写到stdout。
答案 0 :(得分:2)
在这种情况下,如何判断sys.stdout是否已被触摸?
您不能,因为stdout可能是redirected或pipeline中的(通过shell中用于运行Python脚本的命令)。例如,您的用户可以通过将script.py
运行为script.py > /dev/null
来将标准输出重定向到/dev/null
(请参阅null(4)),然后您的问题甚至没有感。而且您的stdout
甚至可能是套接字,fifo,设备等。此外,some_code
的{{3}}-ution可能会更改stdout
(例如,将其关闭,重定向使用exec
,重新定义stdout
Python对象等))
此外,您的程序甚至可能不会在终端中运行(例如os.dup2
作业,或者使用at
或ssh
运行程序)。另请参见t crontab(5)页。
stdout he tty demystified(通常)是由调用过程(通常但并非总是某些shell)设置的,该过程具有standard stream-ed和fork(2)-ed您的脚本。
那不是Linux特有的,它是execve(2)。您可能需要阅读一些Unix或Linux编程书籍(例如Unix philosophy)。
您可以通过使用ALP来检测 stdout 是终端的情况。但这当然不能涵盖所有可能的用例。
Linux具有/proc/
(有关更多信息,请参见isatty(3)),并且stdout也是/dev/stdout
,也可以是/proc/self/fd/1
,您可以在其上执行proc(5)(以及当然您可以直接对fstat
做STDOUT_FILENO
,即1)。但是,即使那样也无法涵盖所有可能的用例。
您是否考虑过程序监视自身的情况(例如pythonp pythonp
...)?
我不确定您的真实目标是什么,但是它们使我心中的stat(2)响了起来,您的问题可能无法确定。
答案 1 :(得分:1)
我通过将sys.stdout.write
和sys.stdout.buffer.write
都包装在python3中来自行解决。
import sys
write = sys.stdout.write
write_called = [False]
def make_write_hook(old_writer, flag: list):
self = old_writer.__self__
def new_writer(value):
self.write = old_writer
flag[0] = True
old_writer(value)
return new_writer
sys.stdout.write = make_write_hook(sys.stdout.write, write_called)
sys.stdout.buffer.write = make_write_hook(
sys.stdout.buffer.write, write_called)
history = []
history.append(write_called[0])
print("hello world")
history.append(write_called[0])
print(history)
# ### output
# hello world
# [False, True]
根据我对cpython的标准库代码的观察,python的约定是,对标准输出的所有写入均应通过调用sys.stdout.write
或sys.stdout.buffer.write
来完成,而不是直接调用os.fdopen(1, 'w').write
之类。这是我的临时结论,我希望比我更了解python的人确认这一点。谢谢大家!