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

时间:2014-01-22 13:53:02

标签: python logging ipython cython ipython-notebook

我正在研究一个混合C ++和Python的模块,通过Cython连接。 C ++代码包括简单的日志记录功能,可将日志语句打印到控制台。 通过Python或IPython命令行使用模块时,会正确打印日志语句。但是,该模块主要用于IPython HTML Notebook。在笔记本中,不显示日志语句。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您可以使用ctypes库并挂钩libc stdout文件描述符来完成此操作:http://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/

我用cython测试了它,它运行正常。

在这里为后代再现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)

并在您的代码中:

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')))

答案 1 :(得分:0)

C / C ++打印到stdout无法重定向,只有python可以。 唯一的方法是让你的c / c ++库接受一个参数,将其日志记录重定向到一个特殊的文件。