簡體   English   中英

如何從 stream 讀取 CSV 文件並在寫入時處理每一行?

[英]How to read a CSV file from a stream and process each line as it is written?

我想從標准輸入中讀取 CSV 文件並處理每一行。 我的 CSV 輸出代碼一行一行地寫入行,但我的讀者在迭代行之前等待 stream 終止。 這是csv模塊的限制嗎? 難道我做錯了什么?

我的閱讀器代碼:

import csv
import sys
import time


reader = csv.reader(sys.stdin)
for row in reader:
    print "Read: (%s) %r" % (time.time(), row)

我的作家代碼:

import csv
import sys
import time


writer = csv.writer(sys.stdout)
for i in range(8):
    writer.writerow(["R%d" % i, "$" * (i+1)])
    sys.stdout.flush()
    time.sleep(0.5)

python 的python test_writer.py | python test_reader.py python test_writer.py | python test_reader.py

Read: (1309597426.3) ['R0', '$']
Read: (1309597426.3) ['R1', '$$']
Read: (1309597426.3) ['R2', '$$$']
Read: (1309597426.3) ['R3', '$$$$']
Read: (1309597426.3) ['R4', '$$$$$']
Read: (1309597426.3) ['R5', '$$$$$$']
Read: (1309597426.3) ['R6', '$$$$$$$']
Read: (1309597426.3) ['R7', '$$$$$$$$']

如您所見,所有打印語句都是同時執行的,但我預計會有 500 毫秒的間隔。

正如文檔中所說

為了使for循環成為循環文件行的最有效方式(一種非常常見的操作), next()方法使用隱藏的預讀緩沖區。

通過查看csv模塊(第 784 行)的實現,您可以看到csv.reader調用了底層迭代器的next()方法(通過PyIter_Next )。

因此,如果您真的想要無緩沖讀取 CSV 文件,則需要將文件 object (此處為sys.stdin )轉換為迭代器,其next()方法實際上調用readline() 這可以使用iter器 function 的兩個參數形式輕松完成。 因此,將test_reader.py中的代碼更改為如下所示:

for row in csv.reader(iter(sys.stdin.readline, '')):
    print("Read: ({}) {!r}".format(time.time(), row))

例如,

$ python test_writer.py | python test_reader.py
Read: (1388776652.964925) ['R0', '$']
Read: (1388776653.466134) ['R1', '$$']
Read: (1388776653.967327) ['R2', '$$$']
Read: (1388776654.468532) ['R3', '$$$$']
[etc]

您能解釋一下為什么需要無緩沖讀取 CSV 文件嗎? 無論您嘗試做什么,都可能有更好的解決方案。

也許這是一個限制。 閱讀此http://docs.python.org/using/cmdline.html#cmdoption-unittest-discover-u

請注意,file.readlines() 和文件對象(用於 sys.stdin 中的行)中有內部緩沖,不受此選項的影響。 要解決這個問題,您需要在 while 1: 循環中使用 file.readline()。

我修改了 test_reader.py 如下:

import csv, sys, time

while True:
    print "Read: (%s) %r" % (time.time(), sys.stdin.readline())

Output

python test_writer.py | python  test_reader.py
Read: (1309600865.84) 'R0,$\r\n'
Read: (1309600865.84) 'R1,$$\r\n'
Read: (1309600866.34) 'R2,$$$\r\n'
Read: (1309600866.84) 'R3,$$$$\r\n'
Read: (1309600867.34) 'R4,$$$$$\r\n'
Read: (1309600867.84) 'R5,$$$$$$\r\n'
Read: (1309600868.34) 'R6,$$$$$$$\r\n'
Read: (1309600868.84) 'R7,$$$$$$$$\r\n'

您正在刷新標准輸出,但不是標准輸入。

Sys.stdin也有一個flush()方法,如果您真的想禁用緩沖,請嘗試在每行讀取后使用該方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM