Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.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 3.x Python通过对命名管道的非阻塞写入避免部分写入_Python 3.x_File Io_Posix - Fatal编程技术网

Python 3.x Python通过对命名管道的非阻塞写入避免部分写入

Python 3.x Python通过对命名管道的非阻塞写入避免部分写入,python-3.x,file-io,posix,Python 3.x,File Io,Posix,我正在linux上运行python3.8 在脚本中,我创建了一个命名管道,并按如下方式打开它: import os import posix import time file_name = 'fifo.txt' os.mkfifo(file_name) f = posix.open(file_name, os.O_RDWR | os.O_NONBLOCK) os.set_blocking(f, False) 在没有打开该文件以便在其他地方读取(例如,使用cat)的情况下,我开始循环写入该文

我正在linux上运行python3.8

在脚本中,我创建了一个命名管道,并按如下方式打开它:

import os
import posix
import time

file_name = 'fifo.txt'
os.mkfifo(file_name)

f = posix.open(file_name, os.O_RDWR | os.O_NONBLOCK)
os.set_blocking(f, False)
在没有打开该文件以便在其他地方读取(例如,使用
cat
)的情况下,我开始循环写入该文件


base_line = 'abcdefghijklmnopqrstuvwxyz'
s = base_line * 10000 + '\n'

while True:
    try:
        posix.write(f, s.encode())
    except BlockingIOError as e:
        print("Exception occurred: {}".format(e))
    time.sleep(.5)
然后,当我使用
cat
读取命名管道时,我发现发生了部分写入

我很困惑如何知道在这个实例中写入了多少字节。由于引发了异常,我无法访问返回值(写入的字节数)。文档表明
BlockingIOError
有一个名为
characters\u writed
的属性,但是当我尝试访问此字段时,会引发
AttributeError


总而言之:首先,我如何避免这种部分写入,或者至少知道在这种情况下有多少部分写入?

os.write
执行无缓冲写入。文档说明当缓冲写入操作将被阻塞时,
BlockingIOError
仅具有
characters\u writed
属性

如果在管道满之前成功写入了任何字节,那么将从
os.write
返回该字节数。否则,您将得到一个异常。当然,驱动器故障之类的情况也会导致异常,即使写入了一些字节。这与POSIX
write
的工作方式没有什么不同,只是在出错时没有返回-1,而是引发了异常

如果不喜欢处理异常,可以在文件描述符周围使用包装器,例如
io.FileIO
对象。我修改了您的代码,因为每次您循环回操作系统时,它都会尝试写入整个缓冲区。write调用(如果失败一次,每次都会失败):


您还可以在的答案中找到一些有用的信息。

谢谢您的回复。我间接地从中得到了答案:)。我假设引发写入调用的第一个异常是部分写入。事实上,部分写入是完全有效的(检查显示的长度是正确的)。在其余部分,休眠而不是选择器用于演示代码。实际上,此代码是更大的执行循环的一部分。再次感谢!
import io
import os
import time

base_line = 'abcdefghijklmnopqrstuvwxyz'
data = (base_line * 10000 + '\n').encode()

file_name = 'fifo.txt'
os.mkfifo(file_name)
fd = os.open(file_name, os.O_RDWR | os.O_NONBLOCK)
# os.O_NONBLOCK makes os.set_blocking(fd, False) unnecessary.

with io.FileIO(fd, 'wb') as f:
    written = 0
    while written < len(data):
        n = f.write(data[written:])
        if n is None:
            time.sleep(.5)
        else:
            written += n
with io.FileIO(fd, 'wb') as f:
    written = 0
    sel = selectors.DefaultSelector()
    sel.register(f, selectors.EVENT_WRITE)
    while written < len(data):
        n = f.write(data[written:])
        if n is None:
            # Wait here until we can start writing again.
            sel.select()
        else:
            written += n
    sel.unregister(f)