Python escribiendo archivos binarios, bytes

Python 3. Estoy usando el widget de diálogo de archivos de QT para guardar archivos PDF descargados de Internet. He estado leyendo el archivo usando ‘abrir’ e intentando escribirlo usando el widget de diálogo del archivo. Sin embargo, me he estado ejecutando en un error “TypeError: ‘_io.BufferedReader’ no es compatible con la interfaz de búfer”.

Código de ejemplo:

with open('file_to_read.pdf', 'rb') as f1: with open('file_to_save.pdf', 'wb') as f2: f2.write(f1) 

Esta lógica funciona correctamente con archivos de texto cuando no se usa el designador ‘b’, o cuando se lee un archivo de la web, como con urllib o solicitudes. Estos son del tipo ‘bytes’, que creo que necesito para abrir el archivo. En su lugar, se está abriendo como un lector almacenado. Intenté los bytes (f1), pero obtuve el mensaje “TypeError: ‘bytes’ no se puede interpretar como un número entero”. ¿Alguna idea?

Si su intención es simplemente hacer una copia del archivo, puede usar shutil

 >>> import shutil >>> shutil.copyfile('file_to_read.pdf','file_to_save.pdf') 

O si necesita acceder a byte a byte, similar a su estructura, esto funciona:

 >>> with open('/tmp/fin.pdf','rb') as f1: ... with open('/tmp/test.pdf','wb') as f2: ... while True: ... b=f1.read(1) ... if b: ... # process b if this is your intent ... n=f2.write(b) ... else: break 

Pero byte a byte es potencialmente muy lento .

O, si desea un búfer que lo acelere (sin correr el riesgo de leer un tamaño de archivo desconocido completamente en la memoria):

 >>> with open('/tmp/fin.pdf','rb') as f1: ... with open('/tmp/test.pdf','wb') as f2: ... while True: ... buf=f1.read(1024) ... if buf: ... for byte in buf: ... pass # process the bytes if this is what you want ... # make sure your changes are in buf ... n=f2.write(buf) ... else: ... break 

Con Python 2.7+ o 3.1+ también puedes usar este atajo (en lugar de usar dos bloques):

 with open('/tmp/fin.pdf','rb') as f1,open('/tmp/test.pdf','wb') as f2: ... 

Realmente no tiene sentido escribir un archivo en otro archivo. Lo que quieres es escribir el contenido de f1 en f2. Obtienes los contenidos con f1.read (). Así que tienes que hacer esto:

 with open('file_to_read.pdf', 'rb') as f1: with open('file_to_save.pdf', 'wb') as f2: f2.write(f1.read()) 

aprendido del python cookbook

 from functools import partial with open(fpath, 'rb') as f, open(target_fpath, 'wb') as target_f: for _bytes in iter(partial(f.read, 1024), ''): target_f.write(_bytes) 

partial(f.read, 1024) devuelve una función, lee el archivo binario 1024 bytes en cada vuelta. iter terminará cuando se encuentre con una blank string '' .