- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我写了一个小基准,比较了 ZOCache 的不同字符串连接方法。
所以这里看起来 tempfile.TemporaryFile 比其他任何东西都快:
$ python src/ZOCache/tmp_benchmark.py
3.00407409668e-05 TemporaryFile
0.385630846024 SpooledTemporaryFile
0.299962997437 BufferedRandom
0.0849719047546 io.StringIO
0.113346099854 concat
我一直在使用的基准代码:
#!/usr/bin/python
from __future__ import print_function
import io
import timeit
import tempfile
class Error(Exception):
pass
def bench_temporaryfile():
with tempfile.TemporaryFile(bufsize=10*1024*1024) as out:
for i in range(0, 100):
out.write(b"Value = ")
out.write(bytes(i))
out.write(b" ")
# Get string.
out.seek(0)
contents = out.read()
out.close()
# Test first letter.
if contents[0:5] != b"Value":
raise Error
def bench_spooledtemporaryfile():
with tempfile.SpooledTemporaryFile(max_size=10*1024*1024) as out:
for i in range(0, 100):
out.write(b"Value = ")
out.write(bytes(i))
out.write(b" ")
# Get string.
out.seek(0)
contents = out.read()
out.close()
# Test first letter.
if contents[0:5] != b"Value":
raise Error
def bench_BufferedRandom():
# 1. BufferedRandom
with io.open('out.bin', mode='w+b') as fp:
with io.BufferedRandom(fp, buffer_size=10*1024*1024) as out:
for i in range(0, 100):
out.write(b"Value = ")
out.write(bytes(i))
out.write(b" ")
# Get string.
out.seek(0)
contents = out.read()
# Test first letter.
if contents[0:5] != b'Value':
raise Error
def bench_stringIO():
# 1. Use StringIO.
out = io.StringIO()
for i in range(0, 100):
out.write(u"Value = ")
out.write(unicode(i))
out.write(u" ")
# Get string.
contents = out.getvalue()
out.close()
# Test first letter.
if contents[0] != 'V':
raise Error
def bench_concat():
# 2. Use string appends.
data = ""
for i in range(0, 100):
data += u"Value = "
data += unicode(i)
data += u" "
# Test first letter.
if data[0] != u'V':
raise Error
if __name__ == '__main__':
print(str(timeit.timeit('bench_temporaryfile()', setup="from __main__ import bench_temporaryfile", number=1000)) + " TemporaryFile")
print(str(timeit.timeit('bench_spooledtemporaryfile()', setup="from __main__ import bench_spooledtemporaryfile", number=1000)) + " SpooledTemporaryFile")
print(str(timeit.timeit('bench_BufferedRandom()', setup="from __main__ import bench_BufferedRandom", number=1000)) + " BufferedRandom")
print(str(timeit.timeit("bench_stringIO()", setup="from __main__ import bench_stringIO", number=1000)) + " io.StringIO")
print(str(timeit.timeit("bench_concat()", setup="from __main__ import bench_concat", number=1000)) + " concat")
编辑 Python3.4.3 + io.BytesIO
python3 ./src/ZOCache/tmp_benchmark.py
2.689500024644076e-05 TemporaryFile
0.30429405899985795 SpooledTemporaryFile
0.348170792000019 BufferedRandom
0.0764778530001422 io.BytesIO
0.05162201000030109 concat
io.BytesIO 的新来源:
#!/usr/bin/python3
from __future__ import print_function
import io
import timeit
import tempfile
class Error(Exception):
pass
def bench_temporaryfile():
with tempfile.TemporaryFile() as out:
for i in range(0, 100):
out.write(b"Value = ")
out.write(bytes(str(i), 'utf-8'))
out.write(b" ")
# Get string.
out.seek(0)
contents = out.read()
out.close()
# Test first letter.
if contents[0:5] != b"Value":
raise Error
def bench_spooledtemporaryfile():
with tempfile.SpooledTemporaryFile(max_size=10*1024*1024) as out:
for i in range(0, 100):
out.write(b"Value = ")
out.write(bytes(str(i), 'utf-8'))
out.write(b" ")
# Get string.
out.seek(0)
contents = out.read()
out.close()
# Test first letter.
if contents[0:5] != b"Value":
raise Error
def bench_BufferedRandom():
# 1. BufferedRandom
with io.open('out.bin', mode='w+b') as fp:
with io.BufferedRandom(fp, buffer_size=10*1024*1024) as out:
for i in range(0, 100):
out.write(b"Value = ")
out.write(bytes(i))
out.write(b" ")
# Get string.
out.seek(0)
contents = out.read()
# Test first letter.
if contents[0:5] != b'Value':
raise Error
def bench_BytesIO():
# 1. Use StringIO.
out = io.BytesIO()
for i in range(0, 100):
out.write(b"Value = ")
out.write(bytes(str(i), 'utf-8'))
out.write(b" ")
# Get string.
contents = out.getvalue()
out.close()
# Test first letter.
if contents[0:5] != b'Value':
raise Error
def bench_concat():
# 2. Use string appends.
data = ""
for i in range(0, 100):
data += "Value = "
data += str(i)
data += " "
# Test first letter.
if data[0] != 'V':
raise Error
if __name__ == '__main__':
print(str(timeit.timeit('bench_temporaryfile()', setup="from __main__ import bench_temporaryfile", number=1000)) + " TemporaryFile")
print(str(timeit.timeit('bench_spooledtemporaryfile()', setup="from __main__ import bench_spooledtemporaryfile", number=1000)) + " SpooledTemporaryFile")
print(str(timeit.timeit('bench_BufferedRandom()', setup="from __main__ import bench_BufferedRandom", number=1000)) + " BufferedRandom")
print(str(timeit.timeit("bench_BytesIO()", setup="from __main__ import bench_BytesIO", number=1000)) + " io.BytesIO")
print(str(timeit.timeit("bench_concat()", setup="from __main__ import bench_concat", number=1000)) + " concat")
每个平台都是这样吗?如果是,为什么?
编辑:具有固定基准(和固定代码)的结果:
0.2675984420002351 TemporaryFile
0.28104681999866443 SpooledTemporaryFile
0.3555715570000757 BufferedRandom
0.10379689100045653 io.BytesIO
0.05650951399911719 concat
最佳答案
你最大的问题:Per tdelaney ,您实际上从未运行过 TemporaryFile
测试;您省略了 timeit
片段中的括号(并且仅针对该测试,其他测试实际上运行了)。因此,您是在计时查找名称 bench_temporaryfile
所花费的时间,而不是实际调用它。变化:
print(str(timeit.timeit('bench_temporaryfile', setup="from __main__ import bench_temporaryfile", number=1000)) + " TemporaryFile")
到:
print(str(timeit.timeit('bench_temporaryfile()', setup="from __main__ import bench_temporaryfile", number=1000)) + " TemporaryFile")
(添加括号使其成为调用)修复。
其他一些问题:
io.StringIO
从根本上不同于您的其他测试用例。具体来说,您正在测试的所有其他类型都以二进制模式运行,读取和写入 str
,并避免行结束转换。 io.StringIO
使用 Python 3 风格的字符串(Python 2 中的 unicode
),您的测试通过使用不同的文字并转换为 unicode
而不是字节
。这增加了大量的编码和解码开销,以及使用更多的内存(unicode
对相同的数据使用 2-4 倍的 str
内存,这意味着更多分配器开销、更多复制开销等)。
另一个主要区别是您为 TemporaryFile
设置了一个真正巨大的 bufsize
;几乎不需要发生系统调用,而且大多数写入只是附加到缓冲区中的连续内存。相比之下,io.StringIO
存储写入的各个值,并且仅在您使用 getvalue()
请求它们时才将它们连接在一起。
此外,最后,您认为通过使用 bytes
构造函数可以向前兼容,但事实并非如此;在 Python 2 中 bytes
是 str
的别名,因此 bytes(10)
返回 '10'
,但在Python 3,bytes
是完全不同的东西,传递一个整数给它返回一个零初始化的 bytes
对象,bytes(10)
返回 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
。
如果你想要一个公平的测试用例,至少切换到 cStringIO.StringIO
或 io.BytesIO
而不是 io.StringIO
并统一写入bytes
。通常,您不会自己显式设置 TemporaryFile
等的缓冲区大小,因此您可能会考虑放弃它。
在我自己的 Linux x64 和 Python 2.7.10 测试中,使用 ipython 的 %timeit
魔法,排名是:
io.BytesIO
每个循环约 48 μsio.StringIO
每个循环约 54 μs(因此 unicode
开销没有增加太多)cStringIO.StringIO
每个循环约 83 μsTemporaryFile
~2.8 ms 每个循环(注意单位;ms 比 μs 长 1000 倍)这还没有返回到默认缓冲区大小(我在您的测试中保留了明确的 bufsize
)。我怀疑 TemporaryFile
的行为会有很大差异(取决于操作系统和临时文件的处理方式;一些系统可能只存储在内存中,其他系统可能存储在 /tmp
,当然,/tmp
可能只是一个 RAMdisk)。
有些事情告诉我你可能有一个设置,其中 TemporaryFile
基本上是一个永远不会进入文件系统的普通内存缓冲区,我的可能最终会在持久存储上结束(如果只是为了短期期);内存中发生的事情是可以预测的,但是当您涉及文件系统时(TemporaryFile
可以,具体取决于操作系统、内核设置等),系统之间的行为会有很大差异。
关于python - tempfile.TemporaryFile 与 StringIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35278482/
我在 Python 中使用 tempfile 和 sqlite3 模块。 以下代码有效: import sqlite3, tempfile conn1 = sqlite3.connect(tempfi
假设我的类如下所示,所有相关导入都已完成: class LargeRequest(server.Request): memory_limit = 1024*1024*25 temp_t
我写了一个小基准,比较了 ZOCache 的不同字符串连接方法。 所以这里看起来 tempfile.TemporaryFile 比其他任何东西都快: $ python src/ZOCache/tmp_
official documentation for TemporaryFile阅读: The mode parameter defaults to 'w+b' so that the file cr
这个问题在这里已经有了答案: How can I check file size in Python? (11 个回答) 3年前关闭。 目前,当我写一个临时: import tempfile a =
我是 python 的新手。我正在学习标准库。 每当我运行下面的代码时,它总是引发 AttributeError...导入命令似乎有问题。 此外,我尝试在交互式解释器上运行它,它工作得很好。 示例代码
在documentation , TemporaryFile() 提到 The returned object is a file-like object whose _file attribute
我正在尝试使用 Scala 和 Play 2.4.6 通过多部分表单数据发送文件。 def sendFile(file: FilePart[TemporaryFile]): Option[Futu
我的环境是Python 3.7.2,在Windows 10上运行。我正在开发一个目录选择小部件,我正在寻找最干净+最可靠的方法来测试所选目录路径是否允许写入权限。 以前,我一直通过通常的 open()
我正在制作一个函数,其目的是获取 mp3文件和 分析处理它。所以,从 this 那里获得帮助所以回答,我正在制作一个临时 wav 文件,然后使用 python ffmpy我正在尝试转换的库 mp3 (
我在使用标准 Django FileField 和 tempfile.TemporaryFile 时遇到问题。每当我尝试使用 TemporaryFile 保存 FileField 时,我都会收到“无法
我通过 use_library 在 Google App Engine 上使用 Django 1.1。这里没有使用 Django GAE helper、Django non-rel 或类似工具。 Dj
我是一名优秀的程序员,十分优秀!