2008-10-22 8 views
13

Quiero hacer algunos filtros básicos en un archivo. Léelo, hazlo, escríbelo.Abrir archivo, leerlo, procesarlo y escribir de nuevo - el método más corto en Python

No estoy buscando "jugar al golf", pero quiero el método más simple y elegante para lograrlo. Se me ocurrió:

from __future__ import with_statement 

filename = "..." # or sys.argv... 

with open(filename) as f: 
    new_txt = # ...some translation of f.read() 

open(filename, 'w').write(new_txt) 

La declaración with hace las cosas más corto ya que no tiene que abrir de forma explícita y cierre el archivo.

¿Alguna otra idea?

Respuesta

25

realidad una forma más fácil usando fileinput es utilizar el parámetro in-situ:

import fileinput 
for line in fileinput.input (filenameToProcess, inplace=1): 
    process (line) 

Si usa el parámetro inplace, redireccionará stdout a su archivo, de modo que si imprime, lo volverá a escribir en su archivo.

este ejemplo se agrega números de línea a su archivo:

import fileinput 

for line in fileinput.input ("b.txt",inplace=1): 
    print "%d: %s" % (fileinput.lineno(),line), 
+0

Muy bien, gracias por señalar esta opción. También puede usar la función filelineno() desde la entrada de archivo para tener automáticamente el número de línea, sin contarlo usted mismo. –

+1

Ah, y se le olvidó la coma después de la impresión - el código agrega líneas adicionales :-) –

+0

Gracias por captar eso - He cambiado el ejemplo. – Hortitude

3

Esto parece funcionar:

with open(filename, "r+") as f: 
    new_txt = process(f.read()) 
    f.truncate(0) 
    f.write(new_txt) 
+0

trabaja aquí solamente al llamar 'f.seek (0)' 'después f.truncate (0)', de lo contrario el nuevo archivo comienza con cero bytes (11 Python 2.7.3 en Linux). – scai

4

me gustaría ir por la elegancia de una manera diferente: poner en práctica sus operaciones de archivo de lectura y filtrado como generadores, usted va a escribir más líneas de código, pero será más código flexible, mantenible y de rendimiento.

Consulte David M. Beazley's Generator Tricks for Systems Programmers, que es algo muy importante para cualquier persona que escriba este tipo de código para leer.

+0

Excelente enlace - ¡gracias! Estoy un poco preocupado por la mayor dificultad en la depuración de tuberías, pero el poder es innegable. –

+1

El desarrollo basado en pruebas es tu amigo. –

2

Si usted está buscando el pitón equivalente de "perl-pi", aquí es una muy buena:

 
import fileinput 
for line in fileinput.input(): 
    # process line 

Ver http://www.python.org/doc/2.5.2/lib/module-fileinput.html por más.

Hecho de esta manera, se utiliza la secuencia de comandos de Python en un tubo para crear el nuevo archivo:

 
$ myscript.py infile.txt > outfile.txt 
+0

No obstante, realmente no me ayuda, ya que quiero volver a escribir en el mismo archivo. Y la redirección no funcionará de esta manera para el mismo archivo –

1

para hacerlo de una manera que no se eat your data si te estrellas en el centro:

from twisted.python.filepath import FilePath 
p = FilePath(filename) 
p.setContent(process(p.getContent())) 
0

Mi fea (pero corto como se indica en la pregunta) solución con generator expressions;

# Some setup first 
file('test.txt', 'w').write('\n'.join('%05d' % i for i in range(100))) 


# This is the filter function 
def f(i): 
    return i % 3 


# This is the main part 
file('test2.txt', 'w').write('\n'.join(str(f(int(l))) for l in file('test.txt', 'r').readlines())) 


# And a wrapper for sanity 
def filter_file(infile, outfile, filter_function) 
    outfile.write('\n'.join(filter_function(l) for l in infile.readlines())) 
Cuestiones relacionadas