Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.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 如何询问管道有多少字节可供读取?_Python_Subprocess_Popen_Nonblocking - Fatal编程技术网

Python 如何询问管道有多少字节可供读取?

Python 如何询问管道有多少字节可供读取?,python,subprocess,popen,nonblocking,Python,Subprocess,Popen,Nonblocking,我已经用Python实现了一个非阻塞读取器,我需要提高它的效率 背景:我需要从一个子进程(从Popen()开始)读取大量的输出并传递给另一个线程。从该子进程读取输出的阻塞时间不得超过几毫秒(最好是读取可用字节所需的最短时间) 目前,我有一个实用程序类,它接受一个文件描述符(stdout)和一个超时。我select()和readline(1)直到发生以下三种情况之一: 我读了一条新行 我的超时(几毫秒)过期 select告诉我该文件描述符上没有可读取的内容 然后我将缓冲文本返回给调用方法,调用方法

我已经用Python实现了一个非阻塞读取器,我需要提高它的效率

背景:我需要从一个子进程(从Popen()开始)读取大量的输出并传递给另一个线程。从该子进程读取输出的阻塞时间不得超过几毫秒(最好是读取可用字节所需的最短时间)

目前,我有一个实用程序类,它接受一个文件描述符(stdout)和一个超时。我
select()
readline(1)
直到发生以下三种情况之一:

  • 我读了一条新行
  • 我的超时(几毫秒)过期
  • select告诉我该文件描述符上没有可读取的内容
  • 然后我将缓冲文本返回给调用方法,调用方法会处理缓冲文本

    现在,真正的问题是:因为我读取了太多的输出,所以我需要提高效率。我想通过询问文件描述符有多少字节是挂起的,然后
    readline([那么多字节])
    。它应该只是传递一些信息,所以我不在乎新行在哪里,甚至不在乎是否有新行我可以询问文件描述符有多少字节可供读取,如果可以,如何读取?

    我做了一些搜索,但我真的很难弄清楚要搜索什么,更不用说是否可能了

    哪怕是正确方向上的一点都会有帮助

    注意:我是在Linux上开发的,但这对于“Pythonic”解决方案来说并不重要。

    在Linux上,
    os.pipe()
    只是管道的包装器(2)。两者都返回一对文件描述符。通常使用lseek(2)(
    os.lseek()
    在Python中)重新定位文件decsriptor的偏移量,作为获取可用数据量的一种方法。但是,并不是所有的文件描述符都能够查找

    在Linux上,在管道上尝试lseek(2)将返回错误,请参阅。这是因为管道或多或少是数据生产者和消费者之间的缓冲区。缓冲区的大小取决于系统

    在Linux上,这是您可以获得的最多数据

    <>强>编辑< /强>:如果你可以改变子进程的工作方式,你可以考虑使用内存映射文件,或者是一个很好的共享内存块。
    Edit2:使用可能比选择更快。

    这个问题似乎提供了一个可能的解决方案,但可能需要重新设置工具

    否则,我假设您知道如何一次读取N个字节的数据:

    all_data = ''
    while True:
        data = pipe.read(1024)   # Reads 1024 bytes or to end of pipe
        if not data:
            break
        all_data += data
        # Add your timeout break here
    

    您可以通过调用os.fstat(file_descriptor)并检查st_size属性(即写入的字节数)来找到这一点

    import os
    reader_file_descriptor, writer_file_descriptor = os.pipe()
    os.write(writer_file_descriptor, b'I am some data')
    readable_bytes = os.fstat(writer_file_descriptor).st_size
    

    下面是一个您应该了解的实用程序:因此,即使我的类通常能够使用lseek()来计算文件描述符中可用的字符数,但如果我向它传递一个stdout管道(来自Popen()),我也无法这样做,对吗?我是否理解正确?有没有其他方法可以让我询问管道等待了多少字节,或者lseek()是完成这类事情的唯一方法?好吧,lseek基本上是唯一的方法。不会
    pipe.read(1024)
    阻塞,直到它得到1024字节或抛出异常(如查找EOF)?另一个问题中的方法似乎很有趣,但不能解决我的特定问题。我有一个非阻塞阅读器,可以工作;我需要知道我是否可以用这种方式进行非阻塞读取;-)是的,它将阻塞直到读取1024字节。您可以将1024设置为任意小,以使其极不可能(但不能保证)超过超时限制。但是你的读线(1)也被阻塞了,对吗?虽然规模较小。是的,这正是我试图解决的问题。因为要读取的字节数无法预测,所以无法选择完美的字节限制。我可以选择一个字节限制,它平均不需要多次阻塞,也不需要多次重复,但这两种情况都是不可取的。我宁愿准确地读取等待的字节数,既不阻塞,也不必返回获取其余的字节。但这似乎是不可能的…@mHurley:fyi,
    os.read(fd,8096)
    可能返回小于
    8096
    字节,即,一个简单的
    select()
    (避免在超时秒内没有可用字节时阻塞)+
    os.read()
    (在
    select()
    之后获取可用数据)可能就足够了。您可以测试
    epoll()
    是否在您的情况下产生更好的结果,并使用
    os.read()
    尝试不同的
    buffersize
    s(越大越好)。