2017-02-01 3 views
1

J'essaie de faire défiler les lignes dans un fichier csv. Je reçois le fichier csv en tant que string à partir d'un site Web. Je sais comment créer csv.reader en utilisant with lorsque les données sont stockées dans un fichier. Qu'est-ce que je ne sais pas, comment obtenir des lignes en utilisant csv.reader sans stocker string dans un fichier. J'utilise Python 2.7.12.Comment utiliser la chaîne comme entrée pour le lecteur csv sans le stocker dans le fichier

J'ai essayé de créer StringIO objet comme celui-ci:

from StringIO import StringIO 

csv_data = "some_string\nfor_example" 
with StringIO(csv_data) as input_file: 
    csv_reader = reader(csv_data, delimiter=",", quotechar='"') 

Cependant, je reçois cette erreur:

Traceback (most recent call last): 
    File "scraper.py", line 228, in <module> 
    with StringIO(csv_data) as input_file: 
AttributeError: StringIO instance has no attribute '__exit__' 

Je comprends que StringIO classe n'a pas __exit__ méthode est appelé quand when finit de faire tout ce qu'il fait avec cet objet.

Ma réponse est comment faire ceci correctement? Je suppose que je peux modifier la classe StringIO en la sous-classant et en ajoutant la méthode __exit__, mais je soupçonne qu'il existe une solution plus facile.

Mise à jour:

Aussi, j'ai essayé différentes combinaisons qui sont venues à l'esprit:

with open(StringIO(csv_data)) as input_file: 

with csv_data as input_file: 

mais, bien sûr, aucun de ceux travaillé.

+2

Il suffit d'utiliser 'input_file = StringIO (csv_data)' au lieu du bloc 'with'. Comment téléchargez-vous les données CSV sur le Web? Vous obtenez généralement un objet fichier lors du téléchargement, qui peut être utilisé directement sans d'abord stocker tout le contenu dans une variable chaîne, puis en enveloppant cette variable dans 'StringIO'. –

+0

Impossible de reproduire en Python 3.5. 'StringIO' peut être utilisé dans un' with'. Quelle est * exactement * votre version et le code? ('from StringIO import StringIO' est * mauvais * ...) –

+0

@SvenMarnach Oui, je peux le faire de cette façon, mais je voudrais utiliser' with'. J'utilise 'requests.get' pour obtenir des données, puis je crée' csv_data' à partir de 'response.text'. – Fejs

Répondre

3
>>> import csv 
>>> csv_data = "some,string\nfor,example" 
>>> result = csv.reader(csv_data.splitlines()) 
>>> list(result) 
[['some', 'string'], ['for', 'example']] 
+0

C'est une bonne solution, merci. – Fejs

+0

Cela ne fonctionnera pas si la chaîne a des sauts de ligne à l'intérieur des valeurs entre guillemets – swooby

0

Si vous aimez les gestionnaires de contexte, vous pouvez utiliser tempfile à la place:

import tempfile 


with tempfile.NamedTemporaryFile(mode='w') as t: 
    t.write('csv_data') 
    t.seek(0) 
    csv_reader = reader(open(t.name), delimiter=",", quotechar='"') 

Comme un avantage de passer lignes de division de chaîne directement au lecteur csv, vous pouvez écrire dans le fichier de toute taille, puis lire en toute sécurité dans lecteur csv sans problèmes de mémoire.

Ce fichier sera fermé et supprimé automatiquement

1

Vous devez utiliser le module io au lieu du StringIO, parce que io.BytesIO pour chaîne d'octets ou io.StringIO pour les Unicode à la fois en charge l'interface du gestionnaire de contexte et peut être utilisé dans with instructions:

from io import BytesIO 
from csv import reader 
csv_data = "some_string\nfor_example" 
with BytesIO(csv_data) as input_file: 
    csv_reader = reader(input_file, delimiter=",", quotechar='"') 
    for row in csv_reader: 
     print row 
+0

Je reçois erreur suivante lorsque j'essaye ceci: 'Traceback (dernier appel dernier): Fichier" scraper.py ", ligne 227, dans avec BytesIO (race_csv_data) comme fichier_entrée: TypeError: 'unicode' n'a pas l'interface tampon' – Fejs

+0

@Fejs Cela signifie que votre 'course_csv_data' est une chaîne unicode et que vous devriez utiliser' io.StringIO' au lieu de 'io.BytesIO '(mais votre exemple utilise une chaîne d'octets ;-) ...) –