草庐IT

python - 快速数据从文件移动到一些 StringIO

coder 2023-08-22 原文

在 Python 中,我有一个文件流,我想将它的一部分复制到 StringIO 中。我希望它尽可能快,副本最少。

但如果我这样做:

data = file.read(SIZE)
stream = StringIO(data)

我认为已经完成了 2 个副本,不是吗?一个从文件复制到数据,另一个在 StringIO 复制到内部缓冲区。我可以避免其中一份副本吗?我不需要临时数据,所以我认为一份就足够了

最佳答案

简而言之:使用 StringIO 无法避免 2 个副本。

一些假设:

  • 你正在使用 cStringIO,否则优化这么多就太傻了。
  • 您追求的是速度而不是内存效率。如果不是,请参阅 Jakob Bowyer 的解决方案,或者如果您的文件是二进制文件,则使用 file.read(SOME_BYTE_COUNT) 的变体。
  • 您已经在评论中说明了这一点,但为了完整起见:您想要实际编辑内容,而不仅仅是查看内容。

长答案:由于 python 字符串是不可变的,而 StringIO 缓冲区不是,迟早要复制一份;否则你会改变一个不可变的对象!对于您希望成为可能的情况,StringIO 对象需要有一个专用方法,该方法直接从作为参数给出的文件对象中读取。没有这样的方法。

在 StringIO 之外,有一些解决方案可以避免额外的复制。在我的脑海中,这将把一个文件直接读入一个可修改的字节数组,没有额外的副本:

import numpy as np
a = np.fromfile("filename.ext", dtype="uint8")

使用起来可能很麻烦,具体取决于您的用途,因为它是一个从 0 到 255 的值数组,而不是一个字符数组。但它在功能上等同于 StringIO 对象,并且使用 np.fromstringnp.tostringnp.tofile 和切片符号应该可以帮助您你要。您可能还需要 np.insertnp.deletenp.append

我确信还有其他模块可以做类似的事情。

时间:

这一切到底有多少重要?好吧,走着瞧。我制作了一个 100MB 的文件,largefile.bin。然后我使用这两种方法读入文件并更改第一个字节。

$ python -m timeit -s "import numpy as np" "a = np.fromfile('largefile.bin', 'uint8'); a[0] = 1"
10 loops, best of 3: 132 msec per loop
$ python -m timeit -s "from cStringIO import StringIO" "a = StringIO(); a.write(open('largefile.bin').read()); a.seek(0); a.write('1')"
10 loops, best of 3: 203 msec per loop

所以在我的例子中,使用 StringIO 比使用 numpy 慢 50%。

最后,为了对比,直接编辑文件:

$ python -m timeit "a = open('largefile.bin', 'r+b'); a.seek(0); a.write('1')"
10000 loops, best of 3: 29.5 usec per loop

所以,它快了将近 4500 倍。当然,这在很大程度上取决于您要对文件执行的操作。改变第一个字节几乎没有代表性。但是使用这种方法,您确实比其他两个方法先行一步,并且由于大多数操作系统都有良好的磁盘缓冲,因此速度也可能非常好。

(如果您不允许编辑文件,因此想避免制作工作副本的成本,有几种可能的方法可以提高速度。如果您可以选择文件系统,Btrfscopy-on-write 文件复制操作——使复制文件的行为几乎是即时的。使用任何文件系统的 LVM 快照可以实现相同的效果。)

关于python - 快速数据从文件移动到一些 StringIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8240647/

有关python - 快速数据从文件移动到一些 StringIO的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  4. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  5. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  6. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  7. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  8. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  9. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  10. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

随机推荐