Использование асинхронного чтения GTK / GIO в Python - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь выполнить асинхронное чтение с помощью GTK / GIO в Python, но хотя само чтение работает нормально (в том смысле, что обратный вызов вызывается только после ввода требуемого количества байтов), я не смогчтобы найти какой-либо способ реального доступа к результату.

Учитывая этот код:

from gi.repository import Gtk, GLib, Gio
import sys

def callback(stream, task):
        result = stream.read_all_finish(task)
        print(stream, task, task.get_user_data(), task.get_task_data(), result, buf)
        Gtk.main_quit()

buf = bytearray(4)

stream = Gio.UnixInputStream.new(sys.stdin.fileno(), False)
stream.read_all_async(buf, GLib.PRIORITY_DEFAULT, None, callback)

Gtk.main()

При запуске он будет ждать, пока не будет введено по крайней мере 4 байта, поэтому один a<return> не приведет к его выходу, но второй будет.Результатом печати будет что-то вроде:

<Gio.UnixInputStream object at 0x7f1045dc3708 (GUnixInputStream at 0x1b8c160)> <Gio.Task object at 0x7f1045dc3bd0 (GTask at 0x1b8e860)> 28890912 28207104 (True, bytes_read=4) bytearray(b'\x00\x00\x00\x00')

Другими словами ...

  • get_user_data() и get_task_data(), похоже, не помогут, так как они возвращают целые числа(значение которого я понятия не имею)
  • Возвращаемое значение из read_all_finish(), похоже, не поможет, так как это просто bool успеха / неудачи плюс поле целого числа bytes_read
  • Буферто, что мы дали read_all_async(), похоже, не поможет, поскольку оно остается неизменным, хотя можно ожидать, что оно будет содержать результат чтения ...

Я также пытался...

  • Проверка тех же вещей перед вызовом read_all_finish(), на случай, если этот вызов по какой-то причине что-то вроде очистки буфера - без кубиков, что дает тот же результат
  • Использование array('b', [0]*4) вместо bytearray - это также дает тот же эффект
  • Использование целого числа вместо buf (поскольку кажется, что более старая версия API работала таким образом)- это просто приводит к TypeError: Must be sequence, not int
  • Использование файла вместо стандартного ввода -без изменений
  • Использование взамен read_async() / read_finish() - без изменений
  • ... и, возможно, еще несколько вещей, которые я даже больше не могу вспомнить

На данный момент я действительно нахожусь в тупике - я просто делаю что-то ужасно неправильно, или привязка Python в GIO ужасно нарушена в отношении асинхронных методов?

1 Ответ

0 голосов
/ 11 июня 2018

Несмотря на то, что не жалуются на стандартный питон bytearray / array, на самом деле он не будет работать с ними;Вам нужно использовать GLib.ByteArray, чтобы он работал.

Другими словами, это будет работать:

from gi.repository import Gtk, GLib, Gio
import sys

def callback(stream, task):
        result = stream.read_all_finish(task)
        print(buf)
        Gtk.main_quit()

buf = GLib.ByteArray.new_take(bytes(4))

stream = Gio.UnixInputStream.new(sys.stdin.fileno(), False)
stream.read_all_async(buf, GLib.PRIORITY_DEFAULT, None, callback)

Gtk.main()
...