如果我们知道所有文件都将加载到内存中,我们可以负担得起, 在python变量中加载整个文件(可能是二进制文件)有什么缺点(如果有的话)或限制(如果有的话)。如果这在技术上是可行的,那么应该避免这种情况,为什么?
关于文件大小问题,应该限制此解决方案的最大大小?为什么?
实际加载代码可以是this stackoverflow entry中提出的代码。
示例代码为:
def file_get_contents(filename):
with open(filename) as f:
return f.read()
content = file_get_contents('/bin/kill')
... code manipulating 'content' ...
[编辑] 想到的代码操作(但可能不适用)是标准列表/字符串运算符(方括号,'+'符号)或一些字符串运算符('len','in'运算符,'count','endswith'/ 'startswith','split','translation'......)。
答案 0 :(得分:11)
一般来说,有更好的方法可以做到这一点,但对于一次性脚本,你知道内存不是问题,当然。
答案 1 :(得分:8)
虽然你得到了很好的回答,但似乎没有人回答你问题的这一部分(正如你在问题中提出许多问题时经常发生的那样;)......:
关于文件大小问题,关于什么 这个解决方案应该是最大尺寸 有限?为什么?
最重要的是,这个特定的Python进程实际上可以使用(所谓的“工作集”)多少物理RAM,而不会过度惩罚整个系统性能的其他方面。如果你的“工作集”超过了物理RAM,那么你将进行分页和交换到磁盘,你的性能会迅速下降(直到所谓的“颠簸”状态基本上所有可用周期都会进入获取页面进出的任务,实际工作量可以忽略不计。)
除此之外,一个相当适度的数量(一般来说最多几MB)可能会被可执行代码(Python自己的可执行文件,DLL或.so)以及字节码和一般支持数据结构所占用。记忆中积极需要的;在一个没有做其他重要或紧急任务的典型现代机器上,与整体可用的数十亿字节相比,你几乎可以忽略这一开销(虽然嵌入式系统的情况可能不同等)。
所有其他内容都可用于您的数据 - 包括您正在读入内存的此文件,以及任何其他重要数据结构。文件数据的“修改”通常可以(暂时)占用文件内容大小的两倍(如果你把它保存在一个字符串中) - 当然,如果你保留一份副本,那么更多旧数据以及制作新修改的副本/版本。
因此,对于典型的现代32位机器上的“只读”使用,例如总体上2GB的RAM,读入内存(比方说)1.5 GB应该没问题;但是如果你正在进行“修改”,它必须大大小于1 GB(如果你在内存中有其他重要的数据结构,那就更少了!)。当然,在具有64位构建的Python,64位操作系统和16 GB RAM的专用服务器上,实际限制在非常不同之前 - 实际上大致与可用RAM的大小不同。
例如,King James的圣经文本可下载here(解压缩)大约4.4 MB;因此,在具有2 GB RAM的计算机中,您可以在内存中保留大约400个略微修改过的副本(如果没有其他请求内存),但是,在具有16(可用且可寻址)GB的RAM的计算机中,您可以保留超过3000份这样的副本。
答案 2 :(得分:4)
with open(filename) as f:
这仅适用于Unix上的Python 2.x.它不会在Python 3.x或Windows上执行您所期望的操作,因为它们在文本和二进制文件之间产生了很大的区别。最好指定文件是二进制文件,如下所示:
with open(filename, 'rb') as f:
这将关闭Windows上的操作系统CR / LF转换,并强制Python 3.x返回字节数组而不是Unicode字符。
关于你的其余问题,我同意Lennart Regebro的(未经编辑的)答案。
答案 3 :(得分:3)
你可以遇到的唯一问题是内存消耗:Python中的字符串是不可变的。因此,当您需要更改字节时,需要复制旧字符串:
new = old[0:pos] + newByte + old[pos+1:]
这需要最多三倍于old
的内存。
您可以使用array代替字符串。如果您需要修改内容,这些可以提供更好的性能,您可以从字符串中轻松创建它们。
答案 4 :(得分:1)
您还可以使用Python的v3功能:
>>> ''.join(open('htdocs/config.php', 'r').readlines())
"This is the first line of the file.\nSecond line of the file"
在此处阅读更多http://docs.python.org/py3k/tutorial/inputoutput.html
答案 5 :(得分:0)
是的,您可以 - 提供的文件足够小 - 。
甚至非常pythonic进一步将read()的返回转换为任何容器/可迭代类型,比如string.split(),以及相关的函数编程功能,以继续“立即”处理文件。 / p>