Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.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 &引用;获取文件位置失败";将ndarray.tofile()和numpy.fromfile()与FIFO一起使用时_Python_Python 3.x_Numpy_Fifo - Fatal编程技术网

Python &引用;获取文件位置失败";将ndarray.tofile()和numpy.fromfile()与FIFO一起使用时

Python &引用;获取文件位置失败";将ndarray.tofile()和numpy.fromfile()与FIFO一起使用时,python,python-3.x,numpy,fifo,Python,Python 3.x,Numpy,Fifo,我正在编写一些虚拟代码,以了解FIFO如何在python中工作(稍后在我正在进行的项目中使用它们)。当我尝试写入或读取时,会收到“OSError:获取文件位置失败”消息 我试图在两个python代码之间传输复杂的数据。我使用FIFO,因为我需要更多不同的通道,以便在运行的模块之间进行通信。我使用bash脚本运行它们,您可以在下面看到 #first.py 将numpy作为np导入 数据=np.complex64([1,2,3]) fifo=打开(“fifoka”、“wb”) 数据文件(fifo)

我正在编写一些虚拟代码,以了解FIFO如何在python中工作(稍后在我正在进行的项目中使用它们)。当我尝试写入或读取时,会收到“OSError:获取文件位置失败”消息

我试图在两个python代码之间传输复杂的数据。我使用FIFO,因为我需要更多不同的通道,以便在运行的模块之间进行通信。我使用bash脚本运行它们,您可以在下面看到

#first.py
将numpy作为np导入
数据=np.complex64([1,2,3])
fifo=打开(“fifoka”、“wb”)
数据文件(fifo)
fifo.flush()
fifo.close()
#second.py
将numpy作为np导入
fifo=打开(“fifoka”、“rb”)
数据=np.fromfile(fifo,数据类型=np.complex64)
fifo.close()
打印(数据)
#/bin/bash
mkfifofifoka
python3 first.py|\
python3秒.py
菲福卡酒店
如果我使用
fifo.write(data.tobytes())
而不是
data.tofile(fifo)
,那么它工作得很好,但根据规则,它应该以同样的方式工作

当我试图从同一个fifo读取数据时,我也有同样的问题,所以我认为我也犯了同样的错误


所以我的问题是,在这种情况下,我应该如何正确地使用
np.fromfile()
ndarray.tofile()

我认为这是由于numpy.ndarray.tofile的工作原理

当fid是文件对象时,数组内容直接写入 文件,绕过文件对象的写入方法。因此,托菲尔 不能与支持压缩的文件对象一起使用(例如。, gzip文件)或不支持fileno()的类文件对象(例如。, BytesIO)


不可能在FIFO中进行搜索


在系统调用级别,
lseek(2)
也用于获取文件位置。所以这也不起作用。

似乎是numpy的一个缺陷。我刚刚遇到了这个问题,将一些代码从Py2.7(numpy版本未知)移动到Py3.8.2(numpy 1.17.4)。将
arr.tofile(fout)
更改为
fout.write(arr.tobytes())
使其正常工作

更好的解决方案:如果要写入的数组是连续的,请使用
fout.write(memoryview(arr))
,这样可以避免复制。如果可能,下面的实用程序将使用
memoryview
,否则
tobytes

def arr_tofile(a,outfile):
    if a.flags['C_CONTIGUOUS']:
        b = memoryview(a)
    else:
        b = a.tobytes()
    outfile.write(b)
十多年来,我一直通过管道使用
arr.tofile(f)
将数据发送到2.x下的其他进程,所以这是一个新缺陷,可能是python 3.x特有的

诚然,文档中说
tofile
绕过
write
方法并使用fd-但没有理由为了执行
tofile
而寻找或告知,也没有理由不在管道上工作

更新-由于兼容性问题,它在python3中不起作用

对于python2操作,tofile中的过程是从python
文件
对象获取
文件*
;然后,要刷新该文件,请获取底层文件号,然后使用
PyArray\u-ToFile
函数写入该文件

显然,由于文件对象中添加了内部缓冲,Python3打破了这一点

现在,它通过调用
npy\u PyFile\u Dup2
从python文件对象生成一个
文件*
,然后使用函数
PyArray\u-ToFile
从该
文件*
写入fd。最后,
npy\u PyFile\u DupClose2(file,fd,orig\u pos)
用于关闭新文件并将原始文件搜索到相同位置。对于python2,将
npy\u PyFile\u Dup2
npy\u PyFile\u Dup2
定义为基本存根;如上所述,使用单个基础
文件*

在Python3中,他们做的更多。我没有详细介绍,但是
npy\u PyFile\u Dup2
实际上使用python机制调用了
os.dup
来创建一个新的文件句柄,并且在写入之后,
npy\u PyFile\u DupClose2
对新文件执行一个“告诉”,然后对原始python文件执行一个“搜索”,跳过刚刚在另一个句柄上写入的数据

底线-这有点混乱-在python3下,最好避免使用
arr.tofile(file)
,即使它可以工作,除非写入的大小足够大,足以证明相当大的开销。而且它对不可查找的文件根本不起作用。在这两种情况下,请使用
file.write(memoryview(arr))
file.write(arr.tobytes())

显而易见的下一个问题-是否可以在管道上解决此问题

也许-它将依赖于能够检测到输出是一个管道,在这种情况下,刷新python文件对象并继续写入其文件句柄(如Python2方法)。写入管道时,无需支持输出文件上的后续“告诉”


抨击

C-API

实用程序函数npy_PyFile_Dup和npy_PyFile_DupClose被应用于其文件对象的内部缓冲python 3破坏。为了修复此问题,在npy_3kcompat.h中声明了两个新函数npy_PyFile_Dup2和npy_PyFile_DupClose2,并且不推荐使用旧函数。由于这些函数的脆弱性,建议尽可能使用python API



为什么在bash中使用pipe
|
?看起来不像是
first.py
正在向
STDOUT
输出任何内容。只需一个接一个地运行
python3 first.py
python3 second.py
,它就会工作。谢谢你的回答,但在我将
|
更改为
&
后,它仍然挂起。我不确定这两种方法为什么不同,但我经历了sa
PyObject *file = (from param)
FILE *fd;
npy_off_t orig_pos = 0;  

fd = npy_PyFile_Dup2(file, "wb", &orig_pos);
if (fd == NULL) {
    goto fail;
}
if (PyArray_ToFile(self, fd, sep, format) < 0) {
    goto fail;
}
if (npy_PyFile_DupClose2(file, fd, orig_pos) < 0) {
    goto fail;
}
if (own && npy_PyFile_CloseFile(file) < 0) {
    goto fail;
}
Py_DECREF(file);
Py_RETURN_NONE;
/*
 * Get a FILE* handle to the file represented by the Python object
 */
static NPY_INLINE FILE*
npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos)
{
    int fd, fd2, unbuf;
    PyObject *ret, *os, *io, *io_raw;
    npy_off_t pos;
    FILE *handle;

    /* For Python 2 PyFileObject, use PyFile_AsFile */
#if !defined(NPY_PY3K)
    if (PyFile_Check(file)) {
        return PyFile_AsFile(file);
    }
#endif

    /* Flush first to ensure things end up in the file in the correct order */

    [[[... continue to call os.dup via python interface....]]]
}
/*
 * Close the dup-ed file handle, and seek the Python one to the current position
 */
static NPY_INLINE int
npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos)
{
    int fd, unbuf;
    PyObject *ret, *io, *io_raw;
    npy_off_t position;

    /* For Python 2 PyFileObject, do nothing */
#if !defined(NPY_PY3K)
    if (PyFile_Check(file)) {
        return 0;
    }
#endif

    position = npy_ftell(handle);

    /* Close the FILE* handle */
    fclose(handle);

    ....[[more]]...