2013-03-08 5 views
6

Ich möchte die Python CSV-Reader verwenden, aber ich möchte in die Zitate verlassen Das ist ich will:.Kann Python CSV-Reader die Zitate in?

>>> s = '"simple|split"|test' 
>>> reader = csv.reader([s], delimiter='|', skipinitialspace=True) 
>>> reader.next() 
['"simple|split"', 'test'] 

Aber ich tatsächlich bekommen:

['simple|split', 'test'] 

In meinem Fall möchte ich die zitierte String, der weitergegeben werden soll, wird immer noch zitiert.

Ich weiß, dass der CSV-Reader wie beabsichtigt funktioniert und mein Anwendungsfall ist ein Missbrauch davon, aber gibt es einen Weg, es nach meinem Willen zu biegen? Oder muss ich meinen eigenen String Parser schreiben?

+0

Sie über muss einen eigenen Parser schreiben. Die Anführungszeichen sind ein Mittel zum Entkommen von Daten, die ansonsten nicht als eine Spalte betrachtet werden würden und daher nicht als Teil der Ausgabe betrachtet werden. –

+1

Je nachdem, wie kompliziert die Daten sind, können Sie möglicherweise etwas Schreckliches wie 'filter (None, re.split (r '(". *? ") | \ |', S)) betrügen und verwenden - oder schauen in 'pyparsing' –

+0

Hallo, ich habe eine Antwort gepostet, in der ich in der Tat entwickle, was Martjin und Jon gesagt haben. Könnten Sie bitte sagen, warum Sie nicht daran gedacht haben, eine Regex zu verwenden? – eyquem

Antwort

3

Sie gehen, um Ihre eigenen Parser, als Teil des Moduls zu schreiben, das Parsen und Zitate sichert ist in der C-Seite der Dinge, insbesondere parse_process_char in Modules/_csv.c gelegen:

else if (c == dialect->quotechar && 
      dialect->quoting != QUOTE_NONE) { 
     if (dialect->doublequote) { 
      /* doublequote; " represented by "" */ 
      self->state = QUOTE_IN_QUOTED_FIELD; 
     } 
     else { 
      /* end of quote part of field */ 
      self->state = IN_FIELD; 
     } 
    } 
    else { 
     /* normal character - save in field */ 
     if (parse_add_char(self, c) < 0) 
      return -1; 
    } 

That "Ende des Zitats Teil des Feldes" Abschnitt ist, was Ihr Doppelzitat chomping ist. Auf der anderen Seite, können Sie möglicherweise die else Bedingung töten und den Python-Quellcode neu erstellen. Aber das ist nicht alles, um ehrlich zu sein.

bearbeiten: Es bedeutete, dass ich das Bit aus dem letzten else hinzufügen, bevor self->state = IN_FIELD so fügt es das Zitat in

+0

Das ist eine ziemlich definitive Antwort! Vielen Dank. –

+0

@HamishDowner Eigentlich hatte ich eine Idee, das Modul PyPy (Python in Python) zu verwenden und es so zu modifizieren, dass es ein benutzerdefiniertes erstellt, das in ein Projekt eingefügt werden kann. Ich werde ein bisschen damit spielen und schauen, ob ich es zur Arbeit bringen kann, damit Sie keine Räder neu erfinden müssen. – cwgem

+1

@HamishDowner Ja, ich habe es versucht, aber PyPys csv-Modul-Code, sogar in Python, hat immer noch viele Pypy-Importe verstreut über. Wäre leider ein bisschen zu viel Aufwand. Vielleicht wollen Sie sich ihren [csv reader code] (https://bitbucket.org/pypy/pypy/src/5a61eff6b57fa1bfa95bd0d04e4a9421dab987ce/pypy/module/_csv/interp_reader.py) ansehen, wenn Sie ein paar Ideen brauchen, wie Sie damit umgehen sollen der Parser funktioniert. – cwgem

2

Ich verstehe nicht, wenn Sie einen klaren Blick auf das, was Sie zu erhalten versuchen..
Sie sagen "Ich weiß (...) mein Anwendungsfall ist ein Missbrauch".
Aber Missbrauch bedeutet, dass die Möglichkeit der Verwendung besteht.
In Ihrem Fall gibt es jedoch keine mögliche Verwendung, was Sie "beschrieben" haben, ist unmöglich, weil das, was an einen CSV-Parser übergeben wird, ein gültiges CSV-Format haben muss und Ihrs nicht.

In einer CSV-gültigen Zeichenfolge sind die meisten Zeichen Informationen und einige Zeichen sind Metainformationen, die zum Interpretieren der Zeichenfolge zum Extrahieren der Informationen erforderlich sind.
Was Sie beschreiben, ist, dass Sie wollen, dass die Zeichen " in der Informationskategorie und Meta-Informationskategorie insgesamt sein sollten. Es ist wie jemand, der seine/ihre linke Hand mit der linken Hand fangen möchte ...

Dieses Problem tritt bei Ihrer Zeichenfolge auf, weil es keine Zeichenfolge aus dem Lesen einer CSV-Datei ist. Es ist eine Zeichenfolge wie sie geschrieben wird.
Es ist unmöglich, eine Zeichenfolge wie diese aus dem Lesen einer CSV-Datei zu erhalten, weil sie nicht so in der CSV-Datei geschrieben werden konnte.
Wenn in eine CSV-Datei geschrieben, '"simple|split"|test'

auf True
  • """simple|split"""|test
    mit doublequote Satz geschrieben werden konnte, ist der Standard

  • oder #"simple#|split#"|test
    mit doublequote = False, escapechar = '#'

.

Wenn Sie die Informationen extrahieren, wie Sie beschrieben, haben Sie nicht einen Parser zu erstellen, müssen Sie nur ein bereits bestehendes Tool verwenden:

import re 

reg = re.compile('".*?"|[^|]+') 

print reg.findall('yoo|"simple|split"|test|end"pos|hu') 

Ergebnis

['yoo', '"simple|split"', 'test', 'end"pos', 'hu']