2013-10-25 14 views
5

Vorrei un modo per fare for line in file in python, dove la fine della riga è ridefinita per essere qualsiasi stringa che voglio. Un altro modo per dire è che voglio leggere i record dal file piuttosto che dalle righe; Voglio che sia altrettanto veloce e conveniente da fare come linee di lettura.Come leggere i record terminati dal separatore personalizzato dal file in python?

Questo è l'equivalente Python per impostare il separatore di record di input $/ di perl o utilizzare Scanner in java. Questo non deve necessariamente usare for line in file (in particolare, l'iteratore potrebbe non essere un oggetto file). Solo qualcosa di equivalente che evita di leggere troppi dati in memoria.

Consulta anche: Add support for reading records with arbitrary separators to the standard IO stack

risposta

8

Non c'è niente in oggetto Python 2.x file, o Python 3.3 io classi, che consente di specificare un delimitatore personalizzato per readline. (Lo for line in file utilizza in ultima analisi lo stesso codice di readline.)

Ma è abbastanza semplice crearlo da solo. Per esempio:

def delimited(file, delimiter='\n', bufsize=4096): 
    buf = '' 
    while True: 
     newbuf = file.read(bufsize) 
     if not newbuf: 
      yield buf 
      return 
     buf += newbuf 
     lines = buf.split(delimiter) 
     for line in lines[:-1]: 
      yield line 
     buf = lines[-1] 

Ecco un esempio stupido di esso in azione:

>>> s = io.StringIO('abcZZZdefZZZghiZZZjklZZZmnoZZZpqr') 
>>> d = delimited(s, 'ZZZ', bufsize=2) 
>>> list(d) 
['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr'] 

Se si vuole farlo bene per entrambi i file binari e di testo, soprattutto in 3. x, è un po 'più complicato. Ma se deve funzionare solo per l'uno o l'altro (e una lingua o l'altra), puoi ignorarlo.

Allo stesso modo, se si utilizza Python 3.x (o utilizzando gli oggetti io in Python 2.x) e si desidera utilizzare i buffer che sono già stati mantenuti in un BufferedIOBase invece di mettere semplicemente un buffer su in cima al buffer, è più difficile. I documenti io spiegano come fare tutto ... ma non conosco esempi semplici, quindi dovrai leggere almeno metà della pagina e sfiorare il resto. (Ovviamente, puoi semplicemente usare i file raw direttamente ... ma non se vuoi trovare delimitatori unicode ...)

+1

Dopo aver letto l'OP il tutto collegato, sembra che Douglas Alan abbia già pubblicato una ricetta molto simile [ 5 anni nella discussione] (http://bugs.python.org/issue1152248#msg109117). Mi piace il suo meglio perché ti permette di trasformare l'input newline in un output newline invece di scartarlo semplicemente ... ma piuttosto che modificare il mio per farlo combaciare, lascerò semplicemente il link. – abarnert

+0

Un altro vantaggio di quello collegato è che restituisce il resto del buffer quando il flusso viene chiuso. – jozxyqk

+0

@jozxyqk: Non sono sicuro di cosa intendi con questo. Questa versione produce il resto del buffer in EOF. (Se il file è effettivamente chiuso da sotto te e generato un'eccezione, presumo tu voglia quell'eccezione - dopotutto, il punto è lavorare come "per file in linea:" ma con un delimitatore diverso). – abarnert

Problemi correlati