передача данных с обратным вызовом

Я создаю асинхронный дочерний процесс с 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 всегда ничего не печатает, так как output перераспределяется в child_read. Теперь вопрос в том, как мне сделать это синтаксически красивым и читаемым (то есть самодокументирующимся) способом? Конечно, я мог бы просто прочитать output в child_done, но тогда вызов child_watch_add не документирует, какие данные используются в обратном вызове. Кроме того, обратный вызов нельзя использовать ни для чего другого. Мне действительно не хватает семантики указателя C/C++, так как это будет делать именно то, что я хочу.

Я также знаю, что я мог бы создать класс wapper, который эмулирует семантику указателя, но это тоже немного раздувает синтаксис. Итак, есть предложения сделать это "pythonic", то есть элегантно, красиво и читабельно?


person Victor Mataré    schedule 23.09.2012    source источник


Ответы (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)

Остальной код не изменился (т. е. по-прежнему используется data=output в вызове child_watch_add().

person Warren Weckesser    schedule 24.09.2012
comment
Да, слышал об этом раньше, но это подходит только потому, что выходные данные используются для сбора данных. Если бы на выходе было всего одно целое число, то обертывание его в список тоже было бы раздуванием. - person Victor Mataré; 24.09.2012
comment
Да, для реализации шаблона, который вы здесь используете, output должен быть изменяемым, а в Python целые числа и строки неизменяемы. (Совершенно ясно, что вы это понимаете; этот комментарий в основном предназначен для тех, кто читает это позже.) - person Warren Weckesser; 24.09.2012