2012-12-17 29 views
4

是否有從文件描述符(不是IO類對象)直接讀入bytearray的方法?python從fd直接讀入bytearray

現在,我使用臨時FileIO對象進行調解,是這樣的:

def fd_readinto(fd, ba): 
    fio = io.FileIO(fd, closefd = False) 
    return fio.readinto(ba) 

回答

1

沒有的功能,這是否和你的方法是目前爲止最快的方法。

我要建議bytearray(mmap)array.fromfile,並且使用bytearraymemoryview甚至一個自制os.read(),但FileIO.readinto尖叫快速

import os 
import mmap, io, array 
import timeit 

fn = 'path_to_largish_file' 

def fd_readinto_mmap(fd, ba): 
    m = mmap.mmap(fd, 0, access=mmap.ACCESS_READ) 
    ba.extend(m) 
    m.close() 

def fd_readinto_fio(fd, ba): 
    with io.FileIO(fd, closefd = False) as fio: 
    fio.readinto(ba) 

def fd_readinto_array(fd, ba): 
    ar = array.array('c') 
    sz = os.fstat(fd).st_size 
    fp = os.fdopen(fd, 'rb') 
    ar.fromfile(fp, sz) 
    ba.extend(ar) 

def fd_readinto_mv(fd, ba): 
    stat = os.fstat(fd) 
    blksize = getattr(stat, 'st_blksize', 4096) 
    bufsize = stat.st_size 
    buf = bytearray(bufsize) 
    m = memoryview(buf) 
    while True: 
     b = os.read(fd, blksize) 
     s = len(b) 
     if not s: break 
     m[:s], m = b, m[s:] 
    writtenbytes = buffer(buf, 0, bufsize-len(m)) 
    ba.extend(writtenbytes) 

setup = """ 
from __main__ import fn, fd_readinto_mmap, fd_readinto_fio, fd_readinto_array, fd_readinto_mv, reset_fd 
import os 
openfd = lambda : os.open(fn, os.O_RDONLY) 
closefd = lambda fd: os.close(fd) 
""" 


reps = 2 
tests = { 
    'fio' : "fd=openfd(); fd_readinto_fio(fd, bytearray()); closefd(fd)", 
    'mmap': "fd=openfd(); fd_readinto_mmap(fd, bytearray()); closefd(fd)", 
    'array': "fd=openfd(); fd_readinto_array(fd, bytearray());", 
    'mv' : "fd=openfd(); fd_readinto_mv(fd, bytearray()); closefd(fd)", 
} 

width = max(map(len, tests)) 
for n,t in tests.iteritems(): 
    time = timeit.timeit(t, setup, number=reps) 
    print ("{:%s} {}" % width).format(n, time) 

在我的系統,FileIO是快幾個數量級。 FileIO.readinto對於文件大小似乎也幾乎是恆定的。 (不知道這怎麼可能。)

mmap 4.86922478676 
array 4.19783091545 
mv 7.75051403046 
fio 9.29832458496e-05 
+6

我不想說這個 - 但你的分析是有缺陷的。根據這些結果,fio的速度比其他所有東西快100,000倍(這導致我的左眉毛提高到相當高的程度)。我花了一些時間檢查你的代碼,發現了這個缺陷。根據文檔(http://docs.python.org/2.7/library/io.html#io.RawIOBase.readinto),「... readinto(b)最多可讀取len(b)個字節......」在你的例子中,你傳遞一個空的bytearray(),所以它返回零字節。如果您預先將bytearray()擴展爲適當的大小,您將獲得更理想的結果。 – user590028