Kódování výstupu procesu volaného pomocí popen – Python – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Kódování výstupu procesu volaného pomocí popen – Python – Fórum – Programujte.comKódování výstupu procesu volaného pomocí popen – Python – Fórum – Programujte.com

 

chalucha
~ Anonymní uživatel
6 příspěvků
25. 7. 2007   #1
-
0
-

Potřebuji přečíst obsah jednoho souboru ze zip souboru, který je navíc chráněn heslem. Kvůli tomu heslu nelze použít zipfile, takže se snažím použít (v linuxu) program unzip s parametrem -p (vypíše obsah do pipe - stdout) a to tak, že zavolám popen(cmd).read(), toto funguje, ale problém je v tom, že textový soubor, který rozbaluji je v kódování cp1250 a nedaří se mi žádným způsobem ho tak přečíst :(
Zkoušel jsem knohovnu codecs, různý způsob konverzí, readstream, ale nic nechodí
Pokud soubor rozbalím do souboru na disku a otevřu až ten, tak to chodí bez problému (codecs.open()), ale tomu bych se rád vyhnul.
Naťukne mne někdo na správnou cestu?

Nahlásit jako SPAM
IP: ...–
geon0
Grafoman
25. 7. 2007   #2
-
0
-

Převod řetězce do unicode nefunguje? - unicode(retezec,"cp1250") ?
A z unicode si ho pak zpětně můžeš převést na jakékoliv jiné. Více na py.cz.

Nahlásit jako SPAM
IP: ...–
geon. volume doprava.
chalucha
~ Anonymní uživatel
6 příspěvků
25. 7. 2007   #3
-
0
-

To geon:
tenhle převod jsem zkoušel jako první, bohužel to ale končí chybou

UnicodeEncodeError: 'ascii' codec can't encode character u'\xfd' in position 8: ordinal not in range(128)


Úsek kódu vypadá takto:


cmd = string.join(["unzip -p -P", self.password, fName, self.vypisyName])
out = commands.getoutput(cmd)
print unicode(out, "cp1250")


podle mého se to už do toho prvního načte ve špatném kódování (jako utf8 které mám nastavené v prostředí?) a pak ten převod selže

zkoušel jsem např. i toto:


csv = os.popen(cmd,'rb')
csv = codecs.getreader("cp1250")(csv)
print csv.read()


se stejnou chybou

Nahlásit jako SPAM
IP: ...–
geon0
Grafoman
25. 7. 2007   #4
-
0
-

Základ tedy je zjistit, jaké je původní kodování - v jakém kodování se ti to tiskne z unzipu na terminál - pokud v utf-8 - tak převod bude vypadat takto: unicode(retezec, "utf8").

Nahlásit jako SPAM
IP: ...–
geon. volume doprava.
chalucha
~ Anonymní uživatel
6 příspěvků
25. 7. 2007   #5
-
0
-

To geon:
Tohle už jsem rovněž zkoušel. Výsledek:

UnicodeDecodeError: 'utf8' codec can't decode bytes in position 8-13: unsupported Unicode code range


Když pustím unzip samotný v terminálu, tak se to taky nevypíše v pořádku, což bych i očekával.
Je nějaký způsob jak zjistit v jakém kódování daný řetězec je?

Jediný rozdíl s tím převodem z utf8 je ten, že když ještě přidám parametr "ignore" pro ignorování chyb, tak ten příkaz projde, ale jsou pryč znaky nad 128. Když konvertuju z cp1250 tak i s ignorováním to hodí chybu.

Moje locale:
LANG=cs_CZ.UTF-8

LC_CTYPE="cs_CZ.UTF-8"
LC_NUMERIC="cs_CZ.UTF-8"
LC_TIME="cs_CZ.UTF-8"
LC_COLLATE="cs_CZ.UTF-8"
LC_MONETARY="cs_CZ.UTF-8"
LC_MESSAGES="cs_CZ.UTF-8"
LC_PAPER="cs_CZ.UTF-8"
LC_NAME="cs_CZ.UTF-8"
LC_ADDRESS="cs_CZ.UTF-8"
LC_TELEPHONE="cs_CZ.UTF-8"
LC_MEASUREMENT="cs_CZ.UTF-8"
LC_IDENTIFICATION="cs_CZ.UTF-8"
LC_ALL=cs_CZ.UTF-8

Nahlásit jako SPAM
IP: ...–
chalucha
~ Anonymní uživatel
6 příspěvků
25. 7. 2007   #6
-
0
-

Update: Před převodem je ještě proměnná typu str

Nahlásit jako SPAM
IP: ...–
geon0
Grafoman
25. 7. 2007   #7
-
0
-

Kodování řetězce se dá zjistit těžko, ale kodování souborů to víceméně jde. Enca a file. Zkus to uložit do souboru a zjistit, v jakém kodování to máš. Možná, že na Linuxech to bude iso-8859-2, ale to jen hádám.

V nejhorším zkus použít file-like objekty, jako StringIO, když ti funguje, jak jsi psal, převod přes soubor.

Nahlásit jako SPAM
IP: ...–
geon. volume doprava.
chalucha
~ Anonymní uživatel
6 příspěvků
25. 7. 2007   #8
-
0
-

To geon:
tak nakonec zafungovalo třeba tohle:

cmd = string.join(["unzip -bp -P", self.password, fName, self.vypisyName])

out = commands.getoutput(cmd)
print out.decode("cp1250")


ale funguje i hned ten první návrh...

problém byl s tím print, které neumí pracovat s unicode, takže pak samo převádí řetězec na kódování os.getdefaultencoding(), což je defaultně ascii a proto ta chyba se znaky nad 127. Dle http://www.diveintopython.org/xml_processing/unicode.html jsem zjistil, že nemám nastavené defaultní kódování v pythonu, takže bylo použito právě ascii, stačilo tedy přidat soubor sitecustomize.py do adresáře pythonu a nastavit v něm kódování na utf8 a už to maká. Ještě jsem zjistil, že se dá ten řetězec vypsat po enkódování na utf8 ručně, takže pak poslední řádek vypadá
print out.decode("cp1250").encode("utf8")
a jede to taky.

I tak ale díky za rady :)

Nahlásit jako SPAM
IP: ...–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 7 hostů

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý