2016-09-16 1 views
0

Contexte: Je prends des données dans mon projet Python/AppEngine et je crée un fichier .tsv pour pouvoir créer des graphiques avec d3.js. En ce moment j'écris le CSV avec chaque chargement de page; Je veux plutôt stocker le fichier une fois dans Google Cloud Storage et le lire à partir de là.Écrire un fichier CSV à stocker dans Google Cloud Storage

Comment je en train d'écrire le fichier, chaque fois que la page est chargée !:

def get(self): ## this gets called when loading myfile.tsv from d3.js 
    datalist = MyEntity.all() 
    self.response.headers['Content-Type'] = 'text/csv' 
    writer = csv.writer(self.response.out, delimiter='\t') 
    writer.writerow(['field1', 'field2']) 
    for eachco in datalist: 
     writer.writerow([eachco.variable1, eachco.variable2]) 

Et tout inefficace, cela fonctionne très bien.

En utilisant this Google Cloud Storage documentation, j'ai essayé d'obtenir quelque chose comme ce travail:

def get(self): 
    filename = '/bucket/myfile.tsv' 
    datalist = MyEntity.all() 
    bucket_name = os.environ.get('BUCKET_NAME', app_identity.get_default_gcs_bucket_name()) 
    write_retry_params = gcs.RetryParams(backoff_factor=1.1) 
    writer = csv.writer(self.response.out, delimiter='\t') 
    gcs_file = gcs.open(filename, 'w', content_type='text/csv', retry_params=write_retry_params) 
    gcs_file.write(writer.writerow(['field1', 'field2'])) 
    for eachco in datalist: 
     gcs_file.write(writer.writerow([eachco.variable1, eachco.variable2])) 
    gcs_file.close() 

Mais je me:

TypeError: Expected str but got <type 'NoneType'>. 

Je pensais que la sortie de csv.writer serait une chaîne de caractères, donc je ne sais pas pourquoi j'obtiens le TypeError.

donc je peux penser à deux situations:

  1. J'ai foiré quelque chose dans mon code qui écrit le TSV à Cloud Storage. Il devrait être simple d'itérer et d'écrire un fichier TSV/CSV dans Cloud Storage, n'est-ce pas?
  2. Je suis allé complètement à ce sujet complètement , et devrait peut-être même utiliser BlobStore ou db.TextProperty() pour stocker ces données .tsv. (Les fichiers ne sont pas si gros, certainement bien moins de 1 Mo)

J'apprécierais toute aide!

modifier - retraçage plein

Traceback (most recent call last): 
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1530, in __call__ 
    rv = self.router.dispatch(request, response) 
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1278, in default_dispatcher 
    return route.handler_adapter(request, response) 
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1102, in __call__ 
    return handler.dispatch() 
    File "/mydirectory/myapp/handlers.py", line 21, in dispatch 
    webapp2.RequestHandler.dispatch(self) 
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 572, in dispatch 
    return self.handle_exception(e, self.app.debug) 
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 570, in dispatch 
    return method(*args, **kwargs) 
    File "/mydirectory/myapp/thisapp.py", line 384, in get 
    gcs_file.write(writer.writerow(['field1', 'field2'])) 
    File "lib/cloudstorage/storage_api.py", line 754, in write 
    raise TypeError('Expected str but got %s.' % type(data)) 
TypeError: Expected str but got <type 'NoneType'>. 
+0

vous oubliez de définir les en-têtes de réponse. –

+0

pouvez-vous ajouter le retraçage complet? –

+0

Je ne sais pas ce que vous essayez d'obtenir avec ce 'gcs_file.write (str (writer.writerow ([eachco.variable1, eachco.variable2])))' ligne. –

Répondre

3

Vous essayez toujours de créer l'écrivain sur une réponse:

writer = csv.writer(self.response.out, delimiter='\t') 

Vous devez écrire dans le fichier GCS. Quelque chose comme ceci:

datalist = MyEntity.all() 
    bucket_name = os.environ.get('BUCKET_NAME', app_identity.get_default_gcs_bucket_name()) 
    filename = os.path.join(bucket_name, 'myfile.tsv') 
    write_retry_params = gcs.RetryParams(backoff_factor=1.1) 
    gcs_file = gcs.open(filename, 'w', content_type='text/csv', retry_params=write_retry_params) 
    writer = csv.writer(gcs_file, delimiter='\t') 
    writer.writerow(['field1', 'field2']) 
    for eachco in datalist: 
     writer.writerow([eachco.variable1, eachco.variable2]) 
    gcs_file.close() 

Notes:

  • pas réellement testé
  • J'ai également ajusté le nom du fichier à utiliser bucket_name
  • si vous le faites dans la demande get() vous pouvez vérifier si le fichier existe déjà et, si c'est le cas, utilisez-le, sinon vous le généreriez toujours à chaque requête. Vous pouvez également déplacer ce code sur une tâche ou dans le gestionnaire de téléchargement .tsv.
+0

Cela fonctionne! Je devais toujours utiliser la ligne filename = '/bucket/myfile.tsv' car c'est le format explicitement requis par GCS. (L'erreur était ValueError: Chemin doit avoir format/bucket/nom de fichier mais a obtenu app_default_bucket/myfile.tsv) –

+0

Ah, manquant leader '/' Je soupçonne. Essayez plutôt 'filename = '/%s/myfile.tsv'% bucket_name' (ce n'est peut-être pas une bonne idée de supposer que le nom de l'application par défaut sera' bucket' en production). –

0

Le problème est que writer.writerow ne retourne rien. Le type de retour sera None, et vous essayez d'écrire cela en gcs_file.