简体   繁体   English

从ipython捕获库f2py调用stdout

[英]Capturing library f2py call stdout from ipython

I'm using Jupyter notebook with a Python 3 kernel. 我正在使用带有Python 3内核的Jupyter笔记本。

If I run: 如果我运行:

import scipy.optimize
scipy.optimize.minimize(
    lambda _: 1,
    0,
    method='COBYLA',
    options={'iprint': 1, 'disp': True, 'maxiter': 2})

I expect to get diagnostic optimization info printed to the ipython notebook. 我希望将诊断优化信息打印到ipython笔记本上。 However, this prints to console. 但是,这将打印到控制台。 I suspect this is the case because the optimization routine is implemented in Fortran, and is interfaced in scipy through f2py. 我怀疑是这种情况,因为优化例程是在Fortran中实现的,并且通过f2py在scipy中进行了接口。 The COBYLA Fortran file does the actual printing. COBYLA Fortran文件执行实际打印。

How can I pipe the Fortran subroutine output to the ipython notebook? 如何将Fortran子例程输出传递给ipython笔记本? As I understand it, it should be the same as calling a compiled C function - so why isn't the stdout shared? 据我了解,它应该与调用已编译的C函数相同-为什么不共享stdout?

The short answer is that you can't. 简短的答案是您不能这样做。 Not easily. 不容易。 That one of the use case that could be covered by the following enhancement proposal to the IPython/Jupyter protocol. 下列对IPython / Jupyter协议的增强建议可以涵盖的用例之一。 Though it's not accepted yet, nor going to happen fast. 尽管尚未接受,但也不会很快发生。

The (hand waved) reason is that when using Python you can monkeypatch sys.stdin/sys.stdout/sys.stderr and write to a file-like interface that redirect to do "The Right Thing"™, though when it's a fortran/c/... functions, they often do directly open the filehandles corresponding to the raw streams, and you can't change this after the fact. (挥手致意)的原因是,使用Python时,您可以对sys.stdin / sys.stdout / sys.stderr进行修补,并写入类似文件的界面以重定向以执行“正确的事情”™,尽管它是fortran / c / ...函数,它们通常会直接打开与原始流相对应的文件句柄,事后您就无法更改它。

The only solution is to control how the process get launched, and change the file descriptor ahead of time, hence the proposal for the "kernel nany". 唯一的解决方案是控制进程的启动方式,并提前更改文件描述符,因此建议使用“内核名”。


Let's develop (after OP further question). 让我们开发(在OP进一步提问之后)。

Python print is a function which does not directly print to standard out, it does in fact write to sys.stdout unless told otherwise. Python print是一个不会直接打印到标准输出的函数,除非另行说明,否则实际上会写入sys.stdout If you check in a normal python shell: 如果您签入普通的python shell:

>>> import sys
>>> sys.stdout
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>

You can see that it is a direct wrapper around a filehandle. 您可以看到它是文件句柄的直接包装器。

If you do the same in a notebook (not in an IPython terminal, that's another story), you will see <ipykernel.iostream.OutStream at 0x104602be0> which is a Proxy object around the ZMQ protocol. 如果您在笔记本中(而不是在IPython终端中,则是另一回事)做同样的事情,您将看到<ipykernel.iostream.OutStream at 0x104602be0> ,它是围绕ZMQ协议的Proxy对象。 In an IPython kernel the previous stream is stored in sys.__stdout__ so you can play around and try a 在IPython内核中,先前的流存储在sys.__stdout__因此您可以尝试一下

sys.__stdout__.write('Hello StackOverflow\n')

Which will print "Hello Stackoverflow" in your notebook server's terminal. 它将在笔记本服务器的终端上打印“ Hello Stackoverflow”。 Do not forget the \\n which trigger the stream to be flushed. 不要忘记\\n触发流被刷新。

Not that this is not a Jupyter behavior, it is an IPython behavior. 并不是说这不是Jupyter行为,而是IPython行为。 The Jupyter side does not care how you do it, as long as you send the stdout over ZMQ. 只要您通过ZMQ发送标准输出,Jupyter一方就不会在乎您如何做。 The Haskell kernel likely does the same by providing it's own io module. Haskell内核可能会通过提供自己的io模块来执行相同的操作。

Capturing the process stdout is one solution (that the kernel nanny proposal covers) but it has its own drawbacks. 捕获进程stdout是一种解决方案(内核保姆提议涵盖),但是它也有其自身的缺点。 It is simpler to redirect at the Python level, as sys.stdout is made for that. 在python级别重定向更容易,因为sys.stdout是为此而创建的。

This behavior is neither a bug nor a "Feature", one could argue that subprocess/f2py/pyc, etc... should be able to handle non-standard stdout/stderr, as argument, and the the nanny is a workaround to help with these case, which will be 这种行为既不是错误也不是“功能”,可能会争辩说subprocess / f2py / pyc等……应该能够处理非标准的stdout / stderr作为参数,而nanny是一种有助于解决问题的解决方法在这些情况下,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM