如何在python中正确处理多个二进制文件?


10

我目前正在借助PycURL模块开发多线程下载器。我正在下载文件的一部分,然后将它们合并。

这些部分是从多个线程中分别下载的,它们以二进制模式写入临时文件,但是当我将它们合并到单个文件(它们以正确的顺序合并)时,校验和不匹配。

这仅在linux env中发生。相同的脚本在Windows env中可以完美地工作。

这是合并文件的代码(脚本的一部分):

with open(filename,'wb') as outfile:
    print('Merging temp files ...')
    for tmpfile in self.tempfile_arr:
        with open(tmpfile, 'rb') as infile:
            shutil.copyfileobj(infile, outfile)
    print('Done!')

我也尝试过 write()method,但是它会导致相同的问题,并且大型文件将占用大量内存。

如果我cat将零件文件手动放入Linux中的单个文件,然后文件的校验和匹配,则问题出在python的文件合并中。

编辑:
这是我用来重现该问题的文件和校验和(sha256):

  • 原始文件
    • 哈希:158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
  • 通过脚本合并的文件
    • 哈希:c3e5a0404da480f36d37b65053732abe6d19034f60c3004a908b88d459db7d87
  • 使用cat手动合并文件

    • 哈希:158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
    • 使用的命令:

      for i in /tmp/pycurl_*_{0..7}; do cat $i >> manually_merged.tar.gz; done
  • 零件文件 -末尾编号,从0到7


2
我认为您的open模式不正确(wb)。根据stackoverflow.com/a/4388244/3727050,您需要ab(或r+bseek
市区,

3
您需要提供一个最小的可重现示例,其中包括一些示例临时文件。我认为您应该能够使用每个仅几个字节的一些临时文件来重现该问题。希望缓冲区大小不是问题的一部分。另外,二进制模式可能并不重要,因此可以使用纯文本文件。
wjandrea

不幸的是,不幸的是,我无法在Linux上用两个非常短的文本文件重现该问题。
wjandrea

实际上pycurl需要二进制模式才能写入数据。
Saumyakanta Sahoo,

3
OK,这些文件的帮助,但你的代码仍然是不完整的: filenameself.tempfile_arr,和shutil是不确定的
wjandrea

Answers:


0

最小限度可重复的情况很方便,但是我怀疑通用换行符会成为问题:默认情况下,如果您的文件是Windows风格的文本(换行符为\r\n),它们将被翻译为Unix风格的换行符(\n)。阅读。然后这些unix样式的换行符将被写回到输出文件,而不是您期望的Windows样式的换行符。那将解释python和cat(不会进行任何翻译)。

尝试运行将newline=''(空字符串)传递给的脚本open

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.