Die Verarbeitung eines Django UploadedFile als UTF-8 mit universal-newlines

In meinem django-Anwendung habe ich ein Formular bereitstellen, die es Benutzern ermöglicht, eine Datei hochzuladen. Die Datei kann in verschiedenen Formaten (Excel, CSV), kommen aus einer Vielzahl von Plattformen (Mac, Linux, Windows), und codiert werden, in eine Vielzahl von Zeichenkodierungen (ASCII, UTF-8).

Für die Zwecke dieser Frage, lassen Sie uns davon ausgehen, dass ich eine Ansicht, die den Empfang request.FILES['file'] eine Instanz von InMemoryUploadedFile genannt file. Mein problem ist, dass InMemoryUploadedFile Objekte (wie file):

  1. Nicht unterstützt UTF-8-Kodierung (ich sehe ein \xef\xbb\xbf am Anfang der Datei, die so wie ich das verstehe ist ein flag, das bedeutet "diese Datei ist UTF-8').
  2. Nicht unterstützen universal-newlines (was wohl die Mehrheit der hochgeladenen Dateien, die auf dieses system benötigen).

Verkompliziert das Problem ist, dass ich wünschte, um übergeben Sie die Datei in der python - csv - Modul, das bietet keine native Unterstützung für Unicode. Ich glücklich akzeptieren Sie Antworten, vermeiden Sie dieses Problem - wenn ich mit django spielen schön mit UTF-8 ich bin sicher, ich kann Keule csv in das gleiche tun. (Ähnlich, bitte ignorieren Sie die Anforderung zur Unterstützung von Excel - ich warte, bis CSV funktioniert, bevor ich angehen Parsen von Excel-Dateien.)

Habe ich versucht, mit StringIO,mmap,codec, und jede einer Vielzahl von Möglichkeiten, auf die Daten in einer InMemoryUploadedFile Objekt. Jeder Ansatz hat ergab unterschiedliche Fehler, keiner ist so weit perfekt gewesen. Dieser zeigt einige der code, den ich fühle, kam der nächste:

import csv
import codecs

class CSVParser:
    def __init__(self,file):
        # 'file' is assumed to be an InMemoryUploadedFile object.
        dialect = csv.Sniffer().sniff(codecs.EncodedFile(file,"utf-8").read(1024))
        file.open() # seek to 0
        self.reader = csv.reader(codecs.EncodedFile(file,"utf-8"),
                                 dialect=dialect)
        try:
            self.field_names = self.reader.next()
        except StopIteration:
            # The file was empty - this is not allowed.
            raise ValueError('Unrecognized format (empty file)')

        if len(self.field_names) <= 1:
            # This probably isn't a CSV file at all.
            # Note that the csv module will (incorrectly) parse ALL files, even
            # binary data. This will catch most such files.
            raise ValueError('Unrecognized format (too few columns)')

        # Additional methods snipped, unrelated to issue

Bitte beachten Sie, dass ich nicht zu viel Zeit auf die eigentliche parsing-Algorithmus, so kann es Wild ineffizient, momentan bin ich mehr mit immer besorgt die Codierung funktioniert wie erwartet.

Das problem ist, dass die Ergebnisse sind auch nicht verschlüsselt, obwohl eingewickelt in die Unicode - codecs.EncodedFile Datei wrapper.

EDIT: Es stellt sich heraus, der obige code funktioniert in der Tat Arbeit. codecs.EncodedFile(file,"utf-8") ist das ticket. Es stellt sich heraus, der Grund, warum ich dachte, dass es nicht funktioniert hat, war, dass die terminal-ich war mit unterstützt nicht UTF-8. Leben und lernen!

  • Ich hatte eine wirklich harte Zeit immer den <code> block zu stoppen kauen bis die '<' und '>' - Zeichen. (Weniger-als und größer-als -, wenn Sie gekaut, bis auch hier.)
  • Ok, nach einiger Zeit der Suche in dieser, es stellt sich heraus, dass der code, den ich oben gepostet hat, in der Tat, Arbeit. Es stellt sich heraus, dass die control-Zeichen, die ich sah, waren da die terminal-ich war mit zu erfassen debug print-Anweisungen nicht unterstützt, ist UTF-8. Woops!
  • Schöne Arbeit, eblume!
InformationsquelleAutor eblume | 2011-01-18
Schreibe einen Kommentar