sys.stdin
对象在Python3中比Python2中更加复杂。例如,默认情况下从sys.stdin
读取输入会将其转换为Unicode,因此对于非Unicode字节会失败:
$ echo -e "\xf8" | python3 -c "import sys; print(sum(1 for _ in sys.stdin))"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 1, in <genexpr>
File "/usr/lib/python3.5/codecs.py", line 321, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf8 in position 0: invalid start byte
请注意,Python2对该输入没有任何问题。因此,您可以看到Python3的
sys.stdin
在幕后执行更多操作。我不确定这是否完全负责性能损失,但您可以通过在Python3下尝试
sys.stdin.buffer
来进一步调查。
import sys
print(sum(1 for _ in sys.stdin.buffer))
请注意,在Python2中不存在
.buffer
。我已经进行了一些测试,发现Python2的
sys.stdin
和Python3的
sys.stdin.buffer
在性能上没有实质区别,但可能因系统而异。
编辑 这里是我机器上的一些随机结果:Ubuntu 16.04,i7 CPU,8GiB RAM。首先是一些C代码(作为比较基准):
#include <unistd.h>
int main() {
char buffer[4096];
size_t total = 0;
while (true) {
int result = ::read(STDIN_FILENO, buffer, sizeof(buffer));
total += result;
if (result == 0) {
break;
}
}
return 0;
};
现在的文件大小为:
$ ls -s --block-size=M | grep huge2.txt
10898M huge2.txt
和测试:
// a.out is a simple C equivalent code (except for the final print)
$ time cat huge2.txt | ./a.out
real 0m20.607s
user 0m0.236s
sys 0m10.600s
$ time cat huge2.txt | python -c "import sys; print(sum(1 for _ in sys.stdin))"
898773889
real 1m24.268s
user 1m20.216s
sys 0m8.724s
$ time cat huge2.txt | python3 -c "import sys; print(sum(1 for _ in sys.stdin.buffer))"
898773889
real 1m19.734s
user 1m14.432s
sys 0m11.940s
$ time cat huge2.txt | python3 -c "import sys; print(sum(1 for _ in sys.stdin))"
898773889
real 2m0.326s
user 1m56.148s
sys 0m9.876s
所以我使用的文件要小一些, 时间会更长(看起来你的机器更好, 而我没有耐心处理更大的文件 :D)。无论如何,根据我的测试,Python2和Python3的sys.stdin.buffer
非常相似。Python3的sys.stdin
速度要慢得多。但是它们都远远落后于C代码(几乎没有用户时间)。
wc
而不是Python呢?cat huge.csv | wc -l
或wc -l huge.csv
。 - mhawkepandas
会更快?或者将文件读入数据库中一次。添加相关索引。使用聚合函数进行查询。 - mhawke