2010-06-03 8 views
7

Me pregunto si alguien con una mejor comprensión de python y gae puede ayudarme con esto. Estoy cargando un archivo csv desde un formulario al almacén de datos de gae.Cargar y analizar el archivo csv con el motor de la aplicación google

class CSVImport(webapp.RequestHandler): 
    def post(self): 
    csv_file = self.request.get('csv_import') 
    fileReader = csv.reader(csv_file) 
    for row in fileReader:  
     self.response.out.write(row) 

estoy corriendo en el mismo problema que otra persona menciona aquí - http://groups.google.com/group/google-appengine/browse_thread/thread/bb2d0b1a80ca7ac2/861c8241308b9717

Es decir, el csv.reader la iteración del cada personaje y no la línea. Un ingeniero de Google dejó esta explicación:

La llamada self.request.get ('csv') devuelve una cadena. Cuando itera sobre una cadena , itera sobre los caracteres, no sobre las líneas. Se puede ver la diferencia aquí:

class ProcessUpload(webapp.RequestHandler): 
    def post(self): 
    self.response.out.write(self.request.get('csv')) 
    file = open(os.path.join(os.path.dirname(__file__), 'sample.csv')) 
    self.response.out.write(file) 

    # Iterating over a file 
    fileReader = csv.reader(file) 
    for row in fileReader: 
     self.response.out.write(row) 

    # Iterating over a string 
    fileReader = csv.reader(self.request.get('csv')) 
    for row in fileReader: 
     self.response.out.write(row) 

Realmente no sigo la explicación, y no tuvo éxito su aplicación. ¿Alguien puede dar una explicación más clara de esto y una solución propuesta?

Gracias, agosto

Respuesta

13

Respuesta corta, intente esto:

fileReader = csv.reader(csv_file.split("\n")) 

Respuesta larga, considere lo siguiente:

for thing in stuff: 
    print thing.strip().split(",") 

Si la materia es un apuntador de archivo, cada cosa es una línea. Si las cosas son una lista, cada cosa es un elemento.Si las cosas son una cadena, cada cosa es un personaje.

Iterar el objeto devuelto por csv.reader le dará un comportamiento similar al de iterar sobre el objeto pasado, solo con cada elemento CSV-analizado. Si itera sobre una cadena, obtendrá una versión analizada por CSV de cada personaje.

+0

Gracias por la explicación, ahora tiene mucho más sentido para mí. –

+0

Consideraría usar .splitlines() en lugar de .split ('\ n') –

8

No puedo pensar en una explicación más clara de lo que el ingeniero de Google que usted ha mencionado, dijo. Así que vamos a analizarlo un poco.

El módulo Python csv opera en objetos de tipo archivo, es decir, un archivo o algo que se comporta como un archivo de Python. Por lo tanto, csv.reader() espera obtener un objeto de archivo ya que solo es un parámetro requerido.

El objeto de solicitud webapp.RequestHandler proporciona acceso a los parámetros HTTP que se publican en el formulario. En HTTP, los parámetros se publican como pares clave-valor, por ejemplo, csv=record_one,record_two. Cuando invoca self.request.get('csv'), se devuelve el valor asociado con la clave csv como cadena de Python. Una cadena de Python no es un objeto similar a un archivo. Aparentemente, el módulo csv está retrocediendo cuando no comprende el objeto y simplemente lo itera (en Python, las cadenas pueden ser repetidas por carácter, por ejemplo, for c in 'Test String': print c imprimirá cada carácter en la cadena en una línea separada).

Afortunadamente, Python proporciona una clase StringIO que permite tratar una cadena como un objeto similar a un archivo. Así que (suponiendo GAE apoya StringIO, y no hay razón para que no debería) que debe ser capaz de hacer esto:

class ProcessUpload(webapp.RequestHandler): 
    def post(self): 
    self.response.out.write(self.request.get('csv')) 

    # Iterating over a string as a file 
    stringReader = csv.reader(StringIO.StringIO(self.request.get('csv'))) 
    for row in stringReader: 
     self.response.out.write(row) 

que funcionará como se espera que lo haga.

Editar Supongo que está utilizando algo así como <textarea/> para recoger el archivo csv. Si está cargando un archivo adjunto, puede ser necesario un manejo diferente (no estoy muy familiarizado con Python GAE o cómo maneja los archivos adjuntos).

+0

Gracias! Esto lo resolvió, y tu explicación fue mucho más fácil de entender para mí. –

+0

@ August Flanagan No creo que la idea expresada en la oración ** El módulo csv de Python opera en objetos similares a archivos, es decir, un archivo o algo que se comporta como un archivo Python. Por lo tanto, csv.reader() espera obtener un objeto de archivo ya que solo es un parámetro requerido. ** es correcto. La documentación dice _ "csv.reader (csvfile, dialect = 'excel', ** fmtparams) Devuelve un objeto lector que iterará sobre líneas en el archivo csv dado. Csvfile puede ser cualquier objeto que admita el protocolo iterador y devuelve una cadena cada uno time su método next() se llama "_ – eyquem

+0

@AugustFlanagan Así que está claro que' 'csv.reader (x)' 'opera en un objeto' 'x'' que no es necesariamente un objeto similar a un archivo, el único requisito es que '' x'' debe ser una cadena iterable y de retorno cuando se itera. – eyquem

0

Debe llamar al csv_file = self.request.POST.get("csv_import") y nocsv_file = self.request.get("csv_import").

El segundo te da una cadena como mencionaste en tu publicación original. Pero accediendo a través de self.request.POST.get le ofrece un objeto cgi.FieldStorage.

Esto significa que puede llamar al csv_file.filename para obtener el nombre del archivo del objeto y csv_file.type para obtener el tipo MIME. Además, si tiene acceso al csv_file.file, es un objeto StringO (un objeto de solo lectura del StringIO module), no solo una cadena. Como se menciona ig0774 en his answer, el módulo StringIO le permite tratar una cadena como un archivo.

Por lo tanto, su código puede ser simplemente:

class CSVImport(webapp.RequestHandler): 
    def post(self): 
    csv_file = self.request.POST.get('csv_import') 
    fileReader = csv.reader(csv_file.file) 
    for row in fileReader: 
     # row is now a list containing all the column data in that row 
     self.response.out.write(row) 
Cuestiones relacionadas