Python中的grep库输出

jmd*_*_dk 6 c python linux grep python-3.x

从命令行调用程序时,我可以管道输出grep以选择我想要查看的行,例如

printf "hello\ngood day\nfarewell\n" | grep day
Run Code Online (Sandbox Code Playgroud)

我正在寻找相同类型的行选择,但是对于从Python调用的C库.请考虑以下示例:

import os

# Function which emulate a C library call
def call_library():
    os.system('printf "hello\ngood day\nfarewell\n"')

# Pure Python stuff
print('hello from Python')
# C library stuff
call_library()
Run Code Online (Sandbox Code Playgroud)

运行这个Python代码时,我希望C部分的输出grep为字符串的ed 'day',从而产生代码的输出

你好,从Python
好日子

到目前为止,我已经stdout使用此处此处描述的方法摆弄了重定向.我能够使C输出完全消失,或将其保存到a str并稍后打印出来(这是两个链接主要关注的内容).然而,我无法根据其内容选择打印哪些行.重要的是,我希望在调用C库时实时输出,所以我不能只是重定向stdout到某个缓冲区并在事后对此缓冲区进行一些处理.

该解决方案只需要在Linux上使用Python 3.x. 如果除了行选择之外,该解决方案还可以进行行编辑,甚至可以更大.

我认为以下应该是可能的,但我不知道如何设置它

  • 重定向stdout到内存中的"文件".

  • 生成一个不断从该文件读取的新线程,根据行内容进行选择,并将所需行写入屏幕,即原始目标stdout.

  • 调用C库

  • 将两个线程重新连接在一起并重定向stdout回其原始目标(屏幕).

我对文件描述符等没有足够的把握能够做到这一点,甚至不知道这是否是最好的方法.

编辑

请注意,解决方案不能简单地重新实现代码call_library.代码必须调用call_library,与实际代码完全无关,然后执行.

zwo*_*wol 5

我对你的程序正在做什么感到有点困惑,但听起来你有一个C 写入C stdout(不是 Python sys.stdout),你想要捕获这个输出并对其进行后处理,你已经有了Python C库的绑定,您更喜欢使用它而不是单独的C程序.

首先,您必须使用子进程来执行此操作; 别的什么都不会可靠.这是因为stdout是进程全局的,所以没有可靠的方法捕获一个线程的写入stdout.

第二关,你可以使用subprocess.Popen,因为你可以使用它重新调用当前脚本!这就是Python multiprocessing模块所做的事情,而且你自己也不是很难.我会使用一个特殊的隐藏命令行参数来区分孩子,如下所示:

import argparse
import subprocess
import sys

def subprocess_call_c_lib():
    import c_lib
    c_lib.do_stuff()

def invoke_c_lib():
    proc = subprocess.Popen([sys.executable, __file__,
                             "--internal-subprocess-call-c-lib"
                             # , ...
                             ],
                            stdin=subprocess.DEVNULL,
                            stdout=subprocess.PIPE)
    for line in proc.stdout:
        # filter output from the library here
        # to display to "screen", write to sys.stdout as usual

    if proc.wait():
        raise subprocess.CalledProcessError(proc.returncode, "c_lib")

def main():
    ap = argparse.Parser(...)
    ap.add_argument("--internal-subprocess-call-c-lib", action="store_true",
                    help=argparse.SUPPRESS)
    # ... more arguments ...

    args = ap.parse_args()
    if args.internal_subprocess_call_c_lib:
        subprocess_call_c_lib()
        sys.exit(0)

    # otherwise, proceed as before ...

main()
Run Code Online (Sandbox Code Playgroud)