2009-07-09 10 views
3

Ich habe eine Datei in UTF-8, in der einige Zeilen das Zeilentrennzeichen U + 2028 enthalten (http://www.fileformat.info/info/unicode/char/2028/index.htm). Ich möchte nicht, dass es als Zeilenumbruch behandelt wird, wenn ich Zeilen aus der Datei lese. Gibt es eine Möglichkeit, es von Separatoren auszuschließen, wenn ich über die Datei iteriere oder readlines() verwende? (Neben dem Lesen der gesamten Datei in eine Zeichenfolge und dann Split durch \ n.) Danke!Ausschließen von U + 2028 aus Zeilentrennzeichen in Python beim Lesen der Datei?

+0

Warum nicht zu U + 2028 übergehen und die Dinosaurier von CR/LF ausgraben? –

Antwort

1

Ich kann dieses Verhalten nicht in Python 2.5 duplizieren, 2.6 oder 3.0 auf Mac OS x - U + 2028 wird immer als nicht-endline behandelt. Können Sie näher darauf eingehen, wo Sie diesen Fehler sehen?

Das heißt, hier ist eine Unterklasse der „Datei“ Klasse, die tun könnte, was Sie wollen:

#/usr/bin/python 
# -*- coding: utf-8 -*- 
class MyFile (file): 
    def __init__(self, *arg, **kwarg): 
     file.__init__(self, *arg, **kwarg) 
     self.EOF = False 
    def next(self, catchEOF = False): 
     if self.EOF: 
      raise StopIteration("End of file") 
     try: 
      nextLine= file.next(self) 
     except StopIteration: 
      self.EOF = True 
      if not catchEOF: 
       raise 
      return "" 
     if nextLine.decode("utf8")[-1] == u'\u2028': 
      return nextLine+self.next(catchEOF = True) 
     else: 
      return nextLine 

A = MyFile("someUnicode.txt") 
for line in A: 
    print line.strip("\n").decode("utf8") 
+0

jemand mit besserem Python-Unicode-Wissen, ist diese Zeile korrekt: 'wenn nextLine.decode (" utf8 ") [- 1] == u '\ u2028':' Ich bekam eine Warnung ohne die Dekodierungsanweisung, don ' Warum nicht? – Markus

+0

Ich weiß nicht, welche Art von Fehlermeldung Sie erhalten, aber wenn die Zeile normalerweise nicht-ASCII-Zeichen enthält, muss sie zuerst in eine 'Unicode-Zeichenfolge' decodiert werden, bevor sie von einer anderen Operation behandelt wird. Also ist es in der Regel 1. decode, 2. tu stuff to string, 3. encode zurück vor dem Schreiben in die Datei, wenn UTF-Dateien behandelt werden. – user135773

0

Wenn Sie Python 3.0 verwenden (beachten Sie, dass ich dies nicht tun, so kann ich nicht testen), nach dem documentation Sie können einen optionalen newline Parameter open passieren, auf die Linie seperator zu verwenden specifify. In der Dokumentation wird jedoch U + 2028 überhaupt nicht erwähnt (es werden nur \r, \n und \r\n als Zeilentrenner erwähnt), also ist es tatsächlich eine Überraschung für mich, dass dies sogar auftritt (obwohl ich dies sogar mit Python 2.6 bestätigen kann). .

2

Ich konnte dieses Verhalten nicht reproduzieren, aber hier ist eine naive Lösung, die nur Leseergebnisse zusammenführt, bis sie nicht mit U + 2028 enden.

#!/usr/bin/env python 

from __future__ import with_statement 

def my_readlines(f): 
    buf = u"" 
    for line in f.readlines(): 
    uline = line.decode('utf8') 
    buf += uline 
    if uline[-1] != u'\u2028': 
     yield buf 
     buf = u"" 
    if buf: 
    yield buf 

with open("in.txt", "rb") as fin: 
    for l in my_readlines(fin): 
    print l 
1

Vielen Dank an alle für die Beantwortung. Ich glaube, ich weiß, warum Sie nicht in der Lage gewesen sein könnten this.I nur zu replizieren erkannte, dass es passiert, wenn ich die Datei dekodieren beim Öffnen, wie in:

f = codecs.open(filename, encoding='utf-8') 
for line in f: 
    print line 

Die Linien sind nicht auf u2028 getrennt, wenn ich öffnen sie die Datei zuerst und dann einzelne Zeilen dekodieren:

f = open(filename) 
for line in f: 
    print line.decode("utf8") 

(ich verwende Python 2.6 unter Windows die Datei war ursprünglich Utf16LE und dann wurde es in UTF-8 konvertiert.).

Das ist sehr interessant, ich schätze, ich werde ab jetzt nicht mehr codecs.open verwenden :-).

0

Das Codecs-Modul macht das Richtige. U + 2028 heißt "LINE SEPARATOR" mit dem Zusatz "kann zur eindeutigen Darstellung dieser Semantik verwendet werden". Es ist also sinnvoll, sie als Linientrenner zu behandeln.

Vermutlich hätte der Ersteller die U + 2028-Zeichen nicht ohne guten Grund eingegeben ... hat die Datei auch "\ n"? Warum sollen Zeilen nicht auf U + 2028 aufgeteilt werden?

+2

Es ist sinnvoll, es als Linienseparator zu behandeln, aber die Frage ist auch sinnvoll. Es gibt Fälle, in denen Datendateien nicht-enantiementierte Zeichenfolgen enthalten, die dieses Zeichen enthalten, und Sie möchten sie verarbeiten, ohne das Zeichen zu unterbrechen. – Nick