Jak poprawnie obsługiwać wiele plików binarnych w Pythonie?

10

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 catpodłą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:

Saumyakanta Sahoo
źródło
2
Myślę, że twój opentryb jest niewłaściwy ( wb). Na podstawie stackoverflow.com/a/4388244/3727050 potrzebujesz ab(lub r+bi seek)
miejskich
3
Musisz podać minimalny odtwarzalny przykład, w tym niektóre przykładowe pliki tymczasowe. Myślę, że powinieneś być w stanie odtworzyć problem z kilkoma plikami tymczasowymi o wielkości zaledwie kilku bajtów. Mam nadzieję, że rozmiar bufora nie jest częścią problemu. Również tryb binarny prawdopodobnie nie jest ważny, więc możesz używać zwykłych plików tekstowych.
wjandrea
FWIW Niestety nie byłem w stanie odtworzyć problemu z dwoma bardzo krótkimi plikami tekstowymi w systemie Linux.
wjandrea
W rzeczywistości pycurl wymaga trybu binarnego do zapisywania danych.
Saumyakanta Sahoo
3
OK, pomoc pliki ale kod jest nadal niekompletna: filename, self.tempfile_arr, i shutilsą niezdefiniowane
wjandrea

Odpowiedzi:

0

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) do open.

Masklinn
źródło