Obecnie pracuję nad wielowątkowym downloaderem z pomocą modułu PycURL. Pobieram części plików i scalam je później.
Części są pobierane oddzielnie od wielu wątków, są zapisywane do plików tymczasowych w trybie binarnym, ale kiedy scalam je w jeden plik (są scalane w odpowiedniej kolejności), sumy kontrolne nie są zgodne.
Dzieje się tak tylko w Linux env. Ten sam skrypt działa bezbłędnie w środowisku Windows Env.
To jest kod (część skryptu), który łączy pliki:
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!')
Próbowałem również write()
metody, ale powoduje to ten sam problem i zajmuje dużo pamięci dla dużych plików.
Jeśli ręcznie cat
podłączyłem pliki części do jednego pliku w systemie Linux, suma kontrolna pliku się zgadza, problem polega na scaleniu plików przez Pythona.
EDYTOWAĆ:
Oto pliki i sumy kontrolne (sha256), których użyłem do odtworzenia problemu:
- Oryginalny plik
- HASH: 158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
- plik scalony przez skrypt
- HASH: c3e5a0404da480f36d37b65053732abe6d19034f60c3004a908b88d459db7d87
plik scalony ręcznie za pomocą cat
- HASH: 158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
Użyte polecenie:
for i in /tmp/pycurl_*_{0..7}; do cat $i >> manually_merged.tar.gz; done
Pliki części - ponumerowane na końcu, od 0 do 7
open
tryb jest niewłaściwy (wb
). Na podstawie stackoverflow.com/a/4388244/3727050 potrzebujeszab
(lubr+b
iseek
)filename
,self.tempfile_arr
, ishutil
są niezdefiniowaneOdpowiedzi:
Przypadek minimalnie powtarzalny byłby wygodny, ale podejrzewam że problemem są uniwersalne znaki nowej linii: domyślnie, jeśli twoje pliki są tekstem w stylu Windows (nowe linie są
\r\n
), zostaną one przetłumaczone na znaki nowej linii w Uniksie (\n
) czytanie. A potem te nowe wiersze w stylu uniksowym zostaną zapisane z powrotem do pliku wyjściowego, a nie w oczekiwanym stylu w stylu Windows. To by tłumaczyło rozbieżność między Pythonem acat
pytonem (który nie zrobiłby żadnego tłumaczenia).Spróbuj uruchomić skrypt przekazując
newline=''
(pusty ciąg) doopen
.źródło