В настоящее время я работаю над многопоточным загрузчиком с помощью модуля 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()
метод, но он приводит к той же самой проблеме, и это займет много памяти для больших файлов.
Если я вручную создаю cat
файлы частей в один файл в linux, то контрольная сумма файла совпадает, проблема заключается в слиянии файлов в python.
РЕДАКТИРОВАТЬ:
Вот файлы и контрольные суммы (sha256), которые я использовал, чтобы воспроизвести проблему:
- Исходный файл
- HASH: 158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
- файл объединен скриптом
- HASH: c3e5a0404da480f36d37b65053732abe6d19034f60c3004a908b88d459db7d87
файл объединен вручную с помощью cat
- HASH: 158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
Используемая команда:
for i in /tmp/pycurl_*_{0..7}; do cat $i >> manually_merged.tar.gz; done
Файлы деталей - нумеруются в конце от 0 до 7
open
режим не подходит (wb
). На основании stackoverflow.com/a/4388244/3727050 вам нужноab
(илиr+b
иseek
)filename
,self.tempfile_arr
иshutil
не определенаОтветы:
Минимально воспроизводимый случай был бы удобен, но я бы предположил, что проблема заключается в универсальных символах новой строки : по умолчанию, если ваши файлы представляют собой текст в стиле Windows (символы новой строки
\r\n
), они будут переведены в символ новой строки Unix (\n
) в чтение. И тогда эти новые строки в стиле Unix будут записаны обратно в выходной файл, а не в стиле Windows, который вы ожидали. Это объяснило бы расхождение между python иcat
(что не переводило бы вообще).Попробуйте запустить свой скрипт, передав
newline=''
(пустую строку) вopen
.источник