2010-12-13 19 views
10

docs El pitón en file.read() estado que An empty string is returned when EOF is encountered immediately. La documentación afirma además:EOF Python para solicitudes múltiples bytes de file.read()

Tenga en cuenta que este método puede llamar a la función C subyacente fread() más de una vez en un esfuerzo por adquirir como cerca de bytes de tamaño como sea posible. También tenga en cuenta que cuando se encuentre en modo sin bloqueo, menos datos que los solicitados pueden ser devueltos, incluso si no se proporcionó el parámetro de tamaño .

Creo que Guido ha hecho su punto de vista sobre no agregar f.eof() PERFECTLY CLEAR así que es necesario usar la forma de Python!

Lo que no está claro para mí, sin embargo, es si es una prueba definitiva que ha llegado a EOF si recibe menos de los bytes solicitados de una lectura, pero recibió algunos.

es decir:

with open(filename,'rb') as f: 
    while True: 
     s=f.read(size) 
     l=len(s) 
     if l==0: 
      break  # it is clear that this is EOF... 
     if l<size: 
      break  # ? Is receiving less than the request EOF??? 

¿Es un error potencial de break si ha recibido menos de los bytes requerida en una llamada a file.read(size)?

Respuesta

21

Usted no está pensando con su piel de serpiente pitón en ... no es C.

En primer lugar, una revisión:

  • st = f.read() lee a EOF, o si se abre como un binario, hasta el último byte;
  • st = f.read (n) intenta para leer n bytes y en ningún caso más de n bytes;
  • st = f.readline() lee una línea a la vez, la línea termina con '\ n' o EOF;
  • st = f.readlines() usa readline() para leer todas las líneas de un archivo y devuelve una lista de las líneas.

Si un método de lectura de archivo está en EOF, devuelve ''. El mismo tipo de prueba EOF se utiliza en los otros métodos 'de tipo archivo' como StringIO, socket.makefile, etc. ¡Una devolución de menos de n bytes desde f.read(n) no es, con seguridad, una prueba de dispositivo para EOF! Mientras que ese código puede funcionar 99 .El 99% del tiempo, son las veces que no funciona que sería muy frustrante de encontrar. Además, es una mala forma de Python. El único uso para n en este caso es poner un límite superior en el tamaño de la devolución.

¿Cuáles son algunas de las razones por las que los métodos similares a los archivos de Python devuelven menos que n bytes?

  1. EOF es ciertamente una razón común;
  2. Un socket de red puede agotar el tiempo de espera en lectura pero permanecer abierto;
  3. Exactamente n bytes puede causar una interrupción entre caracteres lógicos de varios bytes (como \r\n en modo texto y, creo que, un carácter de varios bytes en Unicode) o alguna estructura de datos subyacente desconocida para usted;
  4. El archivo está en modo sin bloqueo y otro proceso comienza a tener acceso al archivo;
  5. No acceso temporal al archivo;
  6. Una condición de error subyacente, potencialmente temporal, en el archivo, disco, red, etc.
  7. El programa recibió una señal, pero el controlador de señal lo ignoró.

Me gustaría volver a escribir el código de esta manera:

with open(filename,'rb') as f: 
    while True: 
     s=f.read(max_size) 
     if not s: break 

     # process the data in s... 

O escribir una generator:

def blocks(infile, bufsize=1024): 
    while True: 
     try: 
      data=infile.read(bufsize) 
      if data: 
       yield data 
      else: 
       break 
     except IOError as (errno, strerror): 
      print "I/O error({0}): {1}".format(errno, strerror) 
      break 

f=open('somefile','rb') 

for block in blocks(f,2**16): 
    # process a block that COULD be up to 65,536 bytes long 
+1

"como \ r \ n en modo binario" <- ¿debería haber dicho "modo de texto" en lugar de "modo binario"? En modo binario, sería un par de bytes como cualquier otro, ¿verdad? –

1

Aquí es lo que dice la documentación de mi C del compilador para la función fread():

size_t fread( 
    void *buffer, 
    size_t size, 
    size_t count, 
    FILE *stream 
); 

fread devuelve el número de elementos completos leen realmente, que puede ser inferior a recuento si se produce un error o si el final del archivo se encuentra antes de contando.

por lo que parece conseguir menos de size medios ya sea un error ha ocurrido o EOF se ha llegado - por lo break ing fuera del circuito sería la cosa correcta de hacer.

+0

Esto no es correcto, una señal puede causar una lectura breve que causa menos bytes para ser devuelto ... que no es exactamente el EOF. – Lekensteyn

+0

@Lekensteyn: Yo diría que si se produce una lectura corta porque el programa recibió una señal, pero el manejador de señal la ignoró, el bucle todavía debe finalizar ya que las señales generalmente indican errores fatales o que los usuarios quieren interrumpir el proceso: - Así que independientemente de si es exactamente un EOF o no, salir del circuito es lo más correcto. – martineau

+0

Estoy de acuerdo en que es sensato que un manejador de señal cause una lectura breve, pero no estoy de acuerdo en que sea una condición de error. Uno de mis scripts sigue procesando datos desde stdin hasta EOF. 'SIGUSR1' está configurado para vaciar datos inmediatamente, esto causa una lectura corta que se espera y * no * un error. – Lekensteyn

Cuestiones relacionadas