【问题标题】:passing data with callback使用回调传递数据
【发布时间】:2012-09-15 08:59:34
【问题描述】:

我正在使用gobject.spawn_async 创建一个异步子进程,它会在标准输出上生成我想在子进程退出时使用的数据。所以我创建了两个回调(最小的例子):

output = ""
def child_read(source, cb_condition):
    for line in source: output += line + "\n"

def child_done(pid, condition, user_data):
    print(user_data)

cpid, cout = gobject.spawn_async(['/bin/ls'],
                      flags = gobject.SPAWN_DO_NOT_REAP_CHILD,
                      standard_output=True)
gobject.child_watch_add(pid=cpid, function=child_done, data=output)
gobject.io_add_watch(os.fdopen(cout, 'r'), gobject.IO_IN | gobject.IO_PRI, child_read)

这里的明显缺陷是child_done 将始终不打印任何内容,因为outputchild_read 中重新分配。现在的问题是,我如何以一种语法上很好且可读(即自我记录)的方式来做到这一点?当然,我可以在child_done 中读取output,但是child_watch_add 调用不会记录回调中使用了哪些数据。加上回调不能用于其他任何事情。我真的在这里缺少 C/C++ 指针语义,因为这正是我想要的。

我也知道我可以创建一个模拟指针语义的 wapper 类,但这也有点使语法膨胀。那么,是否有任何建议以一种美观且易读的方式执行此“pythonic”,即优雅

【问题讨论】:

    标签: python asynchronous callback glib pygobject


    【解决方案1】:

    我没有使用过 gobject,但是对于一个 Python 问题来说,在 SO 上没有答案的时间很长,所以我会试一试。

    使output 成为字符串列表而不是字符串。可能是这样的:

    output = []
    
    def child_read(source, cb_condition):
        output.extend(source)
    
    def child_done(pid, condition, user_data):
        output_str = '\n'.join(user_data)
        print(output_str)
    

    其余代码不变(即在对child_watch_add()的调用中仍使用data=output

    【讨论】:

    • 是的,之前听说过,但它只适合因为输出用于收集数据。如果输出只是一个 int,那么将它包装在一个列表中也会变得臃肿。
    • 是的,要实现您在此处使用的模式output 必须是可变的,并且在 Python 中,整数和字符串是不可变的。 (很明显,您明白这一点;此评论主要是为以后阅读本文的其他人准备的。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-30
    相关资源
    最近更新 更多