我在python中编写了一个小型加密模块,其任务是加密文件并将结果放在tarfile中。要加密的原始文件可以退出大,但这不是问题,因为我的程序一次只需要处理一小块数据,可以动态加密并存储。
我正在寻找一种避免两次传递的方法,首先将所有数据写入临时文件,然后将结果插入tarfile中。
基本上我执行以下操作(其中generator_encryptor是一个简单的生成器,它生成从源文件读取的数据块)。 :
t = tarfile.open("target.tar", "w")
tmp = file('content', 'wb')
for chunk in generator_encryptor("sourcefile"):
tmp.write(chunks)
tmp.close()
t.add(content)
t.close()
我有点恼火不得不使用临时文件,因为我文件应该很容易直接在tar文件中写blocs,但收集单个字符串中的每个块并使用像t.addfile('content'这样的东西,StringIO(bigcipheredstring)似乎被排除在外,因为我不能保证我的内存足够旧的bigcipheredstring。
有任何暗示如何做到这一点?
答案 0 :(得分:4)
您可以创建自己的类文件对象并传递给TarFile.addfile。您的文件类对象将在fileobj.read()方法中动态生成加密内容。
答案 1 :(得分:2)
咦?你不能只使用subprocess模块来运行tar到tar吗?这样,就不需要临时文件了。当然,如果您无法以足够小的块生成数据以适应RAM,这将无法工作,但如果您遇到此问题,则tar不是问题。
答案 2 :(得分:2)
基本上使用类似文件的对象并将其传递给TarFile.addfile可以解决问题,但仍然存在一些问题。
结果代码如下,基本上我必须编写一个包装类,将我现有的生成器转换为类文件对象。我还在我的示例中添加了GeneratorEncrypto类以使代码完成。您可以注意到它有一个len方法,它返回写入文件的长度(但要理解它只是一个没有用处的虚拟占位符)。
import tarfile
class GeneratorEncryptor(object):
"""Dummy class for testing purpose
The real one perform on the fly encryption of source file
"""
def __init__(self, source):
self.source = source
self.BLOCKSIZE = 1024
self.NBBLOCKS = 1000
def __call__(self):
for c in range(0, self.NBBLOCKS):
yield self.BLOCKSIZE * str(c%10)
def __len__(self):
return self.BLOCKSIZE * self.NBBLOCKS
class GeneratorToFile(object):
"""Transform a data generator into a conventional file handle
"""
def __init__(self, generator):
self.buf = ''
self.generator = generator()
def read(self, size):
chunk = self.buf
while len(chunk) < size:
try:
chunk = chunk + self.generator.next()
except StopIteration:
self.buf = ''
return chunk
self.buf = chunk[size:]
return chunk[:size]
t = tarfile.open("target.tar", "w")
tmp = file('content', 'wb')
generator = GeneratorEncryptor("source")
ti = t.gettarinfo(name = "content")
ti.size = len(generator)
t.addfile(ti, fileobj = GeneratorToFile(generator))
t.close()
答案 3 :(得分:1)
我想你需要了解tar格式的工作原理,并自己处理tar写法。也许这会有所帮助?
http://mail.python.org/pipermail/python-list/2001-August/100796.html