我试图捕捉在jupyter笔记本中运行命令时打印到STDERR的内容。特别是,我使用的是TensorFlow,它来自C部分的fprintf
,通常在控制台上打印,但我想保存到Python变量中。在
我一直在使用来自IPython codebase的FDRedirector,它设置os.pipe
将输出捕获到Python字符串中。在
然而,这段代码的问题是它挂起内核以获得足够大的输出。我怀疑它在输出超过65k时会挂起,因为这是Linux上的管道缓冲区大小,gdb
显示挂起发生在write
中。有没有人有一个解决方案可以处理更大的输出?在
{我现在做什么
STDERR = 2
redirect = FDRedirector(STDERR)
import tensorflow as tf
sess = tf.Session("")
node = tf.Print(tf.constant(1), [tf.constant(1)], "longstringlongstring")
def print_to_stderr():
sess.run(node) # this prints to stderr
redirect.start();
print_to_stderr()
captured_stderr = redirect.stop()
最后,“captured\u stderr”包含打印到stderr的所有内容,包括longstringlongstring
。如果您使longstring
部件更长(大于100k),则此部件将冻结。在
希望这对你有用
您可以尝试将输出通过管道传输到临时文件,这样就没有缓冲区限制:
请告诉我这是否对你有用。不幸的是我没有安装TF。在
Jupyter本身在向一个小区输出1Mb数据时幸存了下来:)
FDRedirector
的问题是,它只从管道读取一次。由于管道的生产者端和使用者端都处于同一进程中,一旦缓冲区已满,这将阻塞管道的写入端。解决方法是从读取端连续读取,而不阻塞另一端。一种方法是生成一个消费者线程。在这里有一段代码可以做到这一点:将stderr重定向到管道并使用线程连续读取。在
更新:正如OP的评论所建议的,代码现在是针对python3的。假设您希望捕获的输出是python3字符串(即Unicode字符串),现在,
redirect
将读取的字节转换为字符串。为此,它接受encoding
和errors
参数——就像Python的decode
(并使用相同的默认值)。这解决了一般用例的一个实际问题:如果您想将捕获的数据作为一个字符串进行进一步处理,那么您必须知道stderr是以哪种编码方式写入的。对于另一个答案中的方法也是如此,其中流被重定向到一个文件。{6}你可以用cd6}来修改代码。在然后,}才能看到重定向工作。在
^{pr2}$redirect
上下文管理器可用于临时将任何流重定向到内部缓冲区。注意,在Jupyter下,sys.stderr
是连接到STDERR
的而不是,它是一个ipykernel.iostream.OutStream
对象,模拟Pythonfile
。所以我们必须os.write
到{相关问题 更多 >
编程相关推荐