Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:os.read()在fd上阻塞_Python_Linux - Fatal编程技术网

Python:os.read()在fd上阻塞

Python:os.read()在fd上阻塞,python,linux,Python,Linux,如果fd是bash shell,如何避免行缓冲问题?这似乎有效: #!/usr/local/cpython-3.3/bin/python import os import pty #mport sys import fcntl OFLAGS = None def set_nonblocking(file_handle): """Make a file_handle non-blocking.""" global OFLAGS OFLAGS = fcntl.fcntl

如果fd是bash shell,如何避免行缓冲问题?

这似乎有效:

#!/usr/local/cpython-3.3/bin/python

import os
import pty
#mport sys
import fcntl

OFLAGS = None

def set_nonblocking(file_handle):
    """Make a file_handle non-blocking."""
    global OFLAGS
    OFLAGS = fcntl.fcntl(file_handle, fcntl.F_GETFL)
    nflags = OFLAGS | os.O_NONBLOCK
    fcntl.fcntl(file_handle, fcntl.F_SETFL, nflags)


def main():
    (pid, file_handle) = pty.fork()
    if pid == 0:
        # we're in the child
        os.execl('/bin/sh', '/bin/sh', '-i')
    else:
        #file_handle = os.open('/dev/null', os.O_RDONLY)
        set_nonblocking(file_handle)
        while True:
            try:
                # return 1-n bytes or exception if no bytes
                data = os.read(file_handle, 1024)
            except BlockingIOError:
                #sys.stdout.write('no data read\r')
                pass
            else:
                print(len(data), data)

main()
有时候,处理非阻塞I/O的方法是使用一个线程或子进程,顺便说一句,然后一个线程或子进程可以阻塞,而其他线程或子进程则可以愉快地执行其工作


HTH

以下是我从您的问题和评论中了解到的内容的摘要,以及答案末尾的一个不令人满意的解决方法。总结应该有助于其他人回答您的问题

似乎您有一个非python的程序想要执行可能需要tty的任意shell命令,并且您选择了一个解决方案来执行一个python脚本,该脚本运行pty.spawn/bin/sh、read_回调和write/read到其stdin/stdout

现在有一个问题,您无法找到shell命令的输出结尾,也就是说,您不知道何时停止读取program.py stdout,如果您尝试读取太多,那么您的非python程序将阻塞

首先,os.read-inside-read\u回调不会阻塞。它可能返回少于1024字节,但不会阻塞:

def read_callback(fd):
    data = os.read(fd, 1024) # <-- this doesn't block
    return data 
虽然当父程序尝试读取时,它没有帮助

变通办法 为了避免读取时阻塞,父级可以将正在运行的sh中的PS1环境更改为某个唯一值,或者在每个命令后注入echo-something\u-unique。然后它可以一次读取一个字节,直到它读取唯一的内容。它应该在这一点上停止


作为替代方案,您可以尝试在父级中使管道非阻塞,并一次读取多个字节。或者使用定义明确消息边界的交换协议并逐个运行shell命令,例如,使用pexpect.run在Python端轻松检测输出结束。

选中select module@PasteBT done-no change,添加到列表中。@PasteBT:如果调用读取回调;这意味着os.read不会阻止,也就是说,如果您使用回调,您不需要选择/bin/sh不会退出,直到您在其stdin上说退出退出或EOF。@J.F.Sebastian我不想退出,请参阅文章顶部的上下文。我只是希望能够继续读取输出,而不是在没有输出的情况下被阻塞,因此返回一些信息来告诉控制进程数据没有,而不是被困在等待output.OP以其他语言PHP的脚本运行program.py。假设您的代码在program.py中:从发送给sh的shell命令中查找输出的结尾有什么帮助?为此,检查pid是否已退出是合理的。@dstromberg您能说明一下吗?应该是在循环中使用os.waitpid和WNOHANG选项。谢谢,我想我可以试试看它是如何运行的,然后在出现“黑客”问题时解决这些问题。谢谢你的输入,非常感谢。@OBV:这个词是。我刚刚测试了这个命令;回声识别理论。它不适用于所有交互式程序。。。因为,例如,如果我在任何[5000]上运行netcat:nc-lnvp 5000 output:listing。。。在程序结束之前,它不会回显测试。:/还有其他想法吗?此外,苏,;回声“测试”;不起作用,切换用户后测试不回显。@OBV:两者均按预期工作:等待程序作为代理完成,不会产生更多输出。我们不能使用EOF作为指示器,因为sh仍在运行,只有回显唯一id。即使对于su情况;如果退出会话,您将看到回显输出。nc示例表明,您希望脚本了解任意网络协议,并了解消息(即使是基于消息的协议)何时完成。解决方案是推送数据,而不是轮询数据。如何做到这一点取决于父程序是什么。但是,如果直到程序结束后才收到结束输出信号,您如何对交互式程序上的标准输入做出反应??控制过程是用户和shell之间的中间人。因此,运行程序并由用户与之交互是必要的。