简体   繁体   English

如何在IPython Notebook中显示扩展模块的日志语句

[英]How to show log statements of extension module in IPython Notebook

I am working on a module which is hybrid C++ and Python, connected via Cython. 我正在研究一个混合C ++和Python的模块,通过Cython连接。 The C++ code includes simple logging functionality which prints log statement to the console. C ++代码包括简单的日志记录功能,可将日志语句打印到控制台。 When using the module via the Python or IPython command line, log statements are printed correctly. 通过Python或IPython命令行使用模块时,会正确打印日志语句。 However, the module is meant to be used primarily from the IPython HTML Notebook. 但是,该模块主要用于IPython HTML Notebook。 In the notebook, log statements do not appear. 在笔记本中,不显示日志语句。 How can I fix this? 我怎样才能解决这个问题?

You can do so by using the ctypes library and hooking the libc stdout file descriptor: http://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/ 您可以使用ctypes库并挂钩libc stdout文件描述符来实现: http//eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/

I have tested this with cython and it works fine. 我用cython对它进行了测试,效果很好。

Reproducing the python3 code here for posterity: 在这里为后代再现python3代码:

from contextlib import contextmanager
import ctypes
import io
import os, sys
import tempfile

libc = ctypes.CDLL(None)
c_stdout = ctypes.c_void_p.in_dll(libc, 'stdout')

@contextmanager
def stdout_redirector(stream):
    # The original fd stdout points to. Usually 1 on POSIX systems.
    original_stdout_fd = sys.stdout.fileno()

    def _redirect_stdout(to_fd):
        """Redirect stdout to the given file descriptor."""
        # Flush the C-level buffer stdout
        libc.fflush(c_stdout)
        # Flush and close sys.stdout - also closes the file descriptor (fd)
        sys.stdout.close()
        # Make original_stdout_fd point to the same file as to_fd
        os.dup2(to_fd, original_stdout_fd)
        # Create a new sys.stdout that points to the redirected fd
        sys.stdout = io.TextIOWrapper(os.fdopen(original_stdout_fd, 'wb'))

    # Save a copy of the original stdout fd in saved_stdout_fd
    saved_stdout_fd = os.dup(original_stdout_fd)
    try:
        # Create a temporary file and redirect stdout to it
        tfile = tempfile.TemporaryFile(mode='w+b')
        _redirect_stdout(tfile.fileno())
        # Yield to caller, then redirect stdout back to the saved fd
        yield
        _redirect_stdout(saved_stdout_fd)
        # Copy contents of temporary file to the given stream
        tfile.flush()
        tfile.seek(0, io.SEEK_SET)
        stream.write(tfile.read())
    finally:
        tfile.close()
        os.close(saved_stdout_fd)

and in your code: 在你的代码中:

f = io.BytesIO()

with stdout_redirector(f):
    print('foobar')
    print(12)
    libc.puts(b'this comes from C')
    os.system('echo and this is from echo')
print('Got stdout: "{0}"'.format(f.getvalue().decode('utf-8')))

C/C++ printing to stdout cannot be redirected, only python one can. C / C ++打印到stdout无法重定向,只有python可以。 The only way would be to have your c/c++ library to accept a parameter to redirect its logging to a special file. 唯一的方法是让你的c / c ++库接受一个参数,将其日志记录重定向到一个特殊的文件。

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

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