Come gestire correttamente più file binari in Python?


10

Attualmente sto lavorando su un downloader multi-thread con l'aiuto del modulo PycURL. Sto scaricando parti dei file e unendole successivamente.

Le parti vengono scaricate separatamente da più thread, vengono scritte in file temporanei in modalità binaria, ma quando le unisco in un singolo file (vengono unite nell'ordine corretto), i checksum non corrispondono.

Questo succede solo in Linux Env. Lo stesso script funziona perfettamente in ambiente Windows.

Questo è il codice (parte dello script) che unisce i file:

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!')

Ho provato anche il write()metodo, ma risulta con lo stesso problema e ci vorrà molta memoria per file di grandi dimensioni.

Se catinserisco manualmente i file di parti in un singolo file in Linux, quindi il checksum del file corrisponde, il problema è con l'unione dei file di Python.

EDIT:
Ecco i file e i checksum (sha256) che ho usato per riprodurre il problema:

  • File originale
    • HASH: 158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
  • file unito dallo script
    • HASH: c3e5a0404da480f36d37b65053732abe6d19034f60c3004a908b88d459db7d87
  • file unito manualmente tramite cat

    • HASH: 158575ed12e705a624c3134ffe3138987c64d6a7298c5a81794ccf6866efd488
    • Comando utilizzato:

      for i in /tmp/pycurl_*_{0..7}; do cat $i >> manually_merged.tar.gz; done
  • File di parti : numerati alla fine, da 0 a 7


2
Penso che la tua openmodalità non sia corretta ( wb). Basato su stackoverflow.com/a/4388244/3727050 necessario ab(o r+be seek)
urban

3
È necessario fornire un esempio riproducibile minimo che includa alcuni tempfile di esempio. Penso che dovresti essere in grado di riprodurre il problema con alcuni template di soli pochi byte ciascuno. Speriamo che la dimensione del buffer non faccia parte del problema. Anche la modalità binaria non è probabilmente importante, quindi è possibile utilizzare file di testo semplice.
wjandrea,

FWIW Purtroppo non sono riuscito a riprodurre il problema con due file di testo molto brevi su Linux.
wjandrea,

In realtà pycurl richiede la modalità binaria per scrivere i dati.
Saumyakanta Sahoo,

3
OK, il file di aiuto, ma il codice è ancora incompleto: filename, self.tempfile_arr, e shutilnon sono definiti
wjandrea

Risposte:


0

Un caso minimamente riproducibile sarebbe conveniente, ma sospetto che il problema sia rappresentato dalle newline universali : per impostazione predefinita, se i tuoi file sono in stile Windows (le nuove righe sono \r\n) verranno tradotti in newline in stile Unix ( \n) su lettura. E poi quelle newline in stile unix verranno riscritte nel file di output anziché in quelle in stile Windows che ti aspettavi. Ciò spiegherebbe la divergenza tra Python e cat(che non farebbe alcuna traduzione).

Prova a eseguire lo script passando newline=''(la stringa vuota) a open.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.