1

我使用以下调用来生成一个进程,取回其 stdin、stdout 和 stderr 的文件描述符,并观察其 stdout 上的输出:

[widget.pid,widget.stdin,widget.stdout,widget.stderr] = \
        gobject.spawn_async(['/bin/sed','s/hi/by/g'], 
                            standard_input=True,
                            standard_output=True,
                            standard_error=True
                            )
gobject.io_add_watch(widget.stdout,
                  gobject.IO_IN,
                  getdata)

然后我向widget.stdin 写入行,期望触发回调函数getdata。

我发现只有在到 widget.stdin 的管道被填满后才会调用我的 getdata 回调,而不是在我发送第一个换行符后立即调用。完整的测试程序及其输出在这里。在管道填满或关闭管道之前,我没有收到任何对 getdata 的回调,然后我终于得到了 sed 返回的数据:

#!/usr/bin/env python
# example base.py
import pygtk
pygtk.require('2.0')
import gtk
import gobject
import os
import time
import fcntl

F_SETPIPE_SZ = 1031  # Linux 2.6.35+
F_GETPIPE_SZ = 1032  # Linux 2.6.35+

def data_can_be_sent(source,cb_condition):
    msg = "hi there how are you\n"
    try:
        print "Source, cond, send", source, cb_condition, msg
        #print "Also sending padding x's and a newline to make 512 bytes."
        os.write(source, msg)
        os.write(source,"\n")
        os.write(source,"-"*(510-len(msg)))
        os.write(source,"\n")
        time.sleep(0.1)
    except Exception as e:
        print e
        print "Could not print in data_can_be_sent"
    return True

def getdata(source,cb_condition):
    try:
        p = os.read(source,4096)
        print "Source, cond, get", Base.pipesize, source, cb_condition, "[", p, "]"
    except:
        print "Could not print in getdata."
    return True

class Base:
    pipesize = 0

    def hello(self, widget, data=None):
        print "Hello"
        print gobject
        try:
            print "fstat",os.fstat(widget.stdin)
            print "fsync"
            os.fsync(widget.stdin)
        except AttributeError as e:
            print "Attribute Error",e
            print "Spawning sed process"
            [widget.pid,widget.stdin,widget.stdout,widget.stderr] = \
                gobject.spawn_async(['/bin/sed','s/hi/by/g'], 
                                    standard_input=True,
                                    standard_output=True,
                                    standard_error=True
                                    )
            print widget.pid,widget.stdin,widget.stdout,widget.stderr
            print "Pipe size",fcntl.fcntl(widget.stdin,F_GETPIPE_SZ)
            print "SET Pipe size",fcntl.fcntl(widget.stdin,F_SETPIPE_SZ,10)
            Base.pipesize = fcntl.fcntl(widget.stdin,F_GETPIPE_SZ)
            print "Pipe size",fcntl.fcntl(widget.stdin,F_GETPIPE_SZ)
            gobject.io_add_watch(widget.stdin,
                                 gobject.IO_OUT,
                                 data_can_be_sent)
            gobject.io_add_watch(widget.stdout,
                                 gobject.IO_IN | gobject.IO_PRI,
                                 getdata)
            os.write(widget.stdin, "aaaaaaaaaaaaaaa\n"*64)
            os.write(widget.stdin, "bbbbbbbbbbbbbbb\n"*64)
            os.write(widget.stdin, "ccccccccccccccc\n"*64)
            os.write(widget.stdin, "ddddddddddddddd\n"*64)

        except OSError as e:
            print "NONATTRIB",e.errno
            print "NONATTRIB",e.strerror

    def delete_event(self, width, event, data=None):
        print "delete event, returning False so window is destroyed"
        return False

    def destroy(self, widget, data=None):
        print "destroy received"
        gtk.main_quit()

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("delete_event", self.delete_event)
        # Here we connect the "destroy" event to a signal handler.
        # This event occurs when we call gtk_widget_destroy() on the window,
        # or if we return FALSE in the "delete_event" callback.
        self.window.connect("destroy", self.destroy)

        self.button = gtk.Button("Hello World")
        self.button.connect("clicked", self.hello, None)
        self.window.add(self.button)
        self.button.show()
        self.window.show()

    def main(self):
        gtk.main()

print __name__
if __name__ == "__main__":
    base = Base()
    base.main()

输出如下所示:

$ python pytest.py
__main__
Hello
<module 'gobject' from '/usr/lib/python2.7/dist-packages/gobject/__init__.pyc'>
fstat Attribute Error 'gtk.Button' object has no attribute 'stdin'
Spawning sed process
29594 16 17 19
Pipe size 65536
SET Pipe size 4096
Pipe size 4096
Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, get 4096 17 1 [ aaaaaaaaaaaaaaa
(more a's, b's, c's, and d's)...
ddddddddddddddd
]
Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, get 4096 17 1 [ by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
]
Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

Source, cond, send 16 4 hi there how are you

delete event, returning False so window is destroyed
destroy received
Source, cond, send 16 4 hi there how are you

Source, cond, get 4096 17 1 [ by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
by there how are you

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
]

更新:为了回应下面 drahnr 的评论,我在 C 中使用 gtk 进行了尝试,并调用了

ret = g_spawn_async_with_pipes(".", /* working directory */
             spawn_argv, /* gchar **argv,*/
             NULL, /* gchar **envp,*/
             0L, /* GSpawnFlags flags,*/
             NULL, /* GSpawnChildSetupFunc child_setup,*/
             NULL, /* gpointer user_data,*/
             &pid, /*GPid *child_pid,*/
             &spawn_stdin, /* gint *standard_input,*/
             &spawn_stdout, /* gint *standard_output, */
             &spawn_stderr, /* gint *standard_error, */
             NULL /*GError **error*/
             );

并得到相同的结果;直到至少 4096 个字节被发送到 sed 之后,sed 才会返回,即使每十个字符有一个换行符。

4

0 回答 0