1

I'm trying to do asynchronous reads with GTK/GIO in Python, but while the read itself works okay (in that the callback is called only after the wanted number of bytes has been input), I haven't been able to find any way to actually access the result.

Given this code:

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

When run, it'll wait until at least 4 bytes have been input, so a single a<return> will not cause it to exit, but a second one will. The print will result in something like:

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

In other words...

  • get_user_data() and get_task_data() seem to be of no help, since they return integers (whose meaning I have no clue about)
  • The return value from read_all_finish() seems to be of no help, since it's just a success/fail bool plus a bytes_read integer field
  • The buffer that we gave to read_all_async() seems to be of no help, since it remains unchanged, even though one might expect it to hold the result of the read...

I've also tried...

  • Inspecting the same things before the read_all_finish() call, just in case that call did something like clear the buffer for some reason - no dice, that gives the same result
  • Using array('b', [0]*4) instead of the bytearray - that gives the same effect as well
  • Using an integer count in place of buf (because it seems that an older version of the API worked that way) - that just results in TypeError: Must be sequence, not int
  • Using a file instead of stdin - no change
  • Using read_async()/read_finish() instead - no change
  • ...and probably a few more things I can't even remember anymore

At this point, I'm really at my wit's end here - Am I just doing something horribly wrong, or is GIO's python binding horribly broken with respect to the async methods?

Aleksi Torhamo
  • 6,452
  • 2
  • 34
  • 44

1 Answers1

0

Despite not complaining about a standard python bytearray/array, it won't actually work with those; You need to use a GLib.ByteArray for it to work.

In other words, this'll work:

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()
Aleksi Torhamo
  • 6,452
  • 2
  • 34
  • 44