2010-06-03 6 views
7

Je me demande si quelqu'un avec une meilleure compréhension de python et gae peut m'aider avec cela. Je télécharge un fichier csv d'un formulaire dans le magasin de données gae.Télécharger et analyser le fichier csv avec google app engine

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) 

Je suis en cours d'exécution dans le même problème que quelqu'un d'autre parle ici - http://groups.google.com/group/google-appengine/browse_thread/thread/bb2d0b1a80ca7ac2/861c8241308b9717

C'est, le csv.reader est itérer sur chaque personnage et non la ligne. Un ingénieur de Google a laissé cette explication:

Le self.request.get d'appel ('csv') renvoie une chaîne. Lorsque vous parcourez une chaîne , vous parcourez les caractères, pas les lignes. Vous pouvez voir la différence ici:

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) 

Je ne suis pas l'explication, et sans succès sa mise en œuvre. Quelqu'un peut-il fournir une explication plus claire de ceci et d'une solution proposée?

Merci, Août

Répondre

13

Réponse courte, essayez ceci:

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

Réponse longue, considérer les points suivants:

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

Si substance est un pointeur de fichier, chaque chose est une ligne. Si les choses sont une liste, chaque chose est un élément.Si les choses sont une chaîne, chaque chose est un caractère.

L'itération sur l'objet renvoyé par csv.reader va vous donner un comportement similaire à l'itération sur l'objet transmis, seulement avec chaque élément CSV-analysé. Si vous itérez sur une chaîne, vous obtiendrez une version CSV-analysée de chaque caractère.

+0

Merci pour l'explication, c'est beaucoup plus logique pour moi maintenant. –

+0

J'envisagerais d'utiliser .splitlines() au lieu de .split ('\ n') –

8

Je ne peux pas penser à une explication plus claire que ce que l'ingénieur de Google a dit que vous avez mentionné. Alors décomposons un peu.

Le module Python csv fonctionne sur des objets de type fichier, c'est-à-dire un fichier ou quelque chose qui se comporte comme un fichier Python. Par conséquent, csv.reader() s'attend à obtenir un objet fichier car c'est seulement le paramètre requis.

L'objet de requête webapp.RequestHandler permet d'accéder aux paramètres HTTP affichés dans le formulaire. Dans HTTP, les paramètres sont enregistrés en tant que paires clé-valeur, par exemple, csv=record_one,record_two. Lorsque vous appelez self.request.get('csv') cela renvoie la valeur associée à la clé csv en tant que chaîne Python. Une chaîne Python n'est pas un objet semblable à un fichier. Apparemment, le module csv retombe lorsqu'il ne comprend pas l'objet et ne fait que l'itérer (en Python, les chaînes peuvent être répétées par caractère, par exemple, for c in 'Test String': print c imprime chaque caractère de la chaîne sur une ligne distincte).

Heureusement, Python fournit une classe StringIO qui permet à une chaîne d'être traitée comme un objet semblable à un fichier. Donc, (en supposant GAE soutient StringIO, et il n'y a aucune raison qu'il ne devrait pas), vous devriez être en mesure de le faire:

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) 

qui fonctionnera comme vous attendez.

Modifier Je suppose que vous utilisez quelque chose comme <textarea/> pour collecter le fichier csv. Si vous téléchargez une pièce jointe, une manipulation différente peut être nécessaire (je ne suis pas familier avec Python GAE ou la façon dont il gère les pièces jointes).

+0

Merci! Ceci l'a résolu, et votre explication m'a été beaucoup plus facile à comprendre. –

+0

@August Flanagan Je ne pense pas que l'idée exprimée dans la phrase ** Le module Python csv fonctionne sur des objets de type fichier, c'est-à-dire un fichier ou quelque chose qui se comporte comme un fichier Python. Par conséquent, csv.reader() s'attend à obtenir un objet fichier car c'est seulement le paramètre requis. ** étant correct. La documentation indique _ "csv.reader (csvfile, dialect = 'excel', ** fmtparams) Renvoie un objet lecteur qui va parcourir les lignes dans le fichier csv donné.csvfile peut être n'importe quel objet supportant le protocole itérateur et retourne une chaîne chaque time sa méthode next() est appelée "_ – eyquem

+0

@AugustFlanagan Il est donc clair que' 'csv.reader (x)' 'fonctionne sur un objet' 'x'' qui n'est pas nécessairement un objet semblable à un fichier, la seule exigence est que '' x'' doit être itérable et renvoyer des chaînes lorsqu'il est itéré. – eyquem

0

Vous devez appeler csv_file = self.request.POST.get("csv_import") et pascsv_file = self.request.get("csv_import").

Le second vous donne juste une chaîne comme vous l'avez mentionné dans votre message original. Mais l'accès via self.request.POST.get vous donne un objet cgi.FieldStorage. Cela signifie que vous pouvez appeler csv_file.filename pour obtenir le nom de fichier de l'objet et csv_file.type pour obtenir le type MIME. En outre, si vous accédez à csv_file.file, il s'agit d'un objet StringO (un objet en lecture seule issu du StringIO module), et pas seulement une chaîne. Comme ig0774 mentionné dans his answer, le module StringIO vous permet de traiter une chaîne comme un fichier.

Par conséquent, votre code peut être simplement:

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) 
Questions connexes