Mam długą listę nazw domen, na których muszę generować raporty. Lista zawiera kilka domen IDN i chociaż wiem, jak je przekonwertować w Pythonie w wierszu poleceń:
>>> domain = u"pfarmerü.com"
>>> domain
u"pfarmerxfc.com"
>>> domain.encode("idna")
"xn--pfarmer-t2a.com"
>>>
Staram się, aby działał z małym skryptem odczytującym dane z pliku tekstowego.
#!/usr/bin/python
import sys
infile = open(sys.argv[1])
for line in infile:
print line,
domain = unicode(line.strip())
print type(domain)
print "IDN:", domain.encode("idna")
print
Otrzymuję następujące wyniki:
$ ./idn.py ./test
pfarmer.com
<type "unicode">
IDN: pfarmer.com
pfarmerü.com
Traceback (most recent call last):
File "./idn.py", line 9, in <module>
domain = unicode(line.strip())
UnicodeDecodeError: "ascii" codec can"t decode byte 0xfc in position 7: ordinal not in range(128)
Próbowałem również:
#!/usr/bin/python
import sys
import codecs
infile = codecs.open(sys.argv[1], "r", "utf8")
for line in infile:
print line,
domain = line.strip()
print type(domain)
print "IDN:", domain.encode("idna")
print
Co dało mi:
$ ./idn.py ./test
Traceback (most recent call last):
File "./idn.py", line 8, in <module>
for line in infile:
File "/usr/lib/python2.6/codecs.py", line 679, in next
return self.reader.next()
File "/usr/lib/python2.6/codecs.py", line 610, in next
line = self.readline()
File "/usr/lib/python2.6/codecs.py", line 525, in readline
data = self.read(readsize, firstline=True)
File "/usr/lib/python2.6/codecs.py", line 472, in read
newchars, decodedbytes = self.decode(data, self.errors)
UnicodeDecodeError: "utf8" codec can"t decode bytes in position 0-5: unsupported Unicode code range
Oto mój plik danych testowych:
pfarmer.com
pfarmerü.com
Jestem bardzo świadomy mojej potrzeby zrozumienia Unicode teraz.
Dzięki,
Piotr
Odpowiedzi:
13 dla odpowiedzi nr 1musisz wiedzieć, w którym kodowaniu zapisałeś plik. Byłoby to coś w rodzaju „utf-8” (który NIE jest Unicode) lub „iso-8859-1” lub „cp1252” lub podobnie.
Wtedy możesz to zrobić (zakładając „utf-8”):
infile = open(sys.argv[1])
for line in infile:
print line,
domain = line.strip().decode("utf-8")
print type(domain)
print "IDN:", domain.encode("idna")
print
Konwertuj zakodowane ciągi znaków na unicode decode
. Konwertuj Unicode na ciąg znaków encode
. Jeśli spróbujesz zakodować coś, co jest już zakodowane, python próbuje najpierw zdekodować, z domyślnym kodekiem „ascii”, który nie działa dla wartości innych niż ASCII.
2 dla odpowiedzi nr 2
Twój pierwszy przykład jest w porządku, z wyjątkiem:
domain = unicode(line.strip())
musisz tutaj podać konkretne kodowanie: unicode(line.strip(), "utf-8")
. W przeciwnym razie otrzymasz domyślne kodowanie, które dla bezpieczeństwa jest 7-bitowe ASCII, stąd błąd. Alternatywnie możesz to przeliterować line.strip().decode("utf-8")
jak w przykładzie knitti, nie ma różnicy w zachowaniu między dwiema składniami.
Jednak sądząc po błędzie „nie można„ dekodować bajtu 0xfc ”, myślę, że właściwie nie zapisałeś swojego test
plik jako utf-8. Przypuszczalnie dlatego drugi przykład, który zasadniczo również wygląda dobrze, zawodzi.
Zamiast tego jest ISO-8859-1 lub bardzo podobnyStrona kodowa Windows 1252. Jeśli pochodzi z edytora tekstowego w oknie Western Windows, z pewnością będzie to druga; maszyny Linux używają teraz domyślnie utf-8. Upewnij się, że zapisałeś plik jako utf-8 lub przeczytaj plik za pomocą kodowania "cp1252"
zamiast.