{"id":1614,"date":"2016-12-28T14:26:03","date_gmt":"2016-12-28T13:26:03","guid":{"rendered":"http:\/\/www.venco.com.pl\/~cozy\/blog\/?p=1614"},"modified":"2016-12-28T14:26:03","modified_gmt":"2016-12-28T13:26:03","slug":"kodowanie-danych-tekstowych-w-pythonie","status":"publish","type":"post","link":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/2016\/12\/28\/kodowanie-danych-tekstowych-w-pythonie\/","title":{"rendered":"Kodowanie danych tekstowych w Pythonie"},"content":{"rendered":"<p>\u017ar\u00f3d\u0142o:\u00a0https:\/\/pl.python.org\/forum\/index.php?topic=5190.0<\/p>\n<p>Dane tekstowe w Pythonie 2.x (bo z kontekstu rozumiem, \u017ce o Pythonie 2.x tu mowa) mog\u0105 by\u0107 reprezentowane na dwa sposoby:<\/p>\n<p>1. Obiekt typu <i>str<\/i> czyli <b>ci\u0105g bajt\u00f3w<\/b> (czyli posta\u0107, w jakiej dane wyst\u0119puj\u0105 w plikach na dysku, w komunikacji przez sie\u0107 itp.) &#8212; np. s\u0142owo <i>\u0142\u00f3d\u017a<\/i> b\u0119dzie mia\u0142o r\u00f3\u017cn\u0105 posta\u0107 w zale\u017cno\u015bci od zastosowanego <b><i>kodowania<\/i><\/b>, np. w kodowaniu <i>windows-1250<\/i> b\u0119dzie to <tt>'\\xb3\\xf3d\\x9f'<\/tt> (4 bajty: 0xb3, 0xf3, 0x64, 0x9f [zauwa\u017cmy, \u017ce bajt 0x64, jako kod drukowalnego znaku ze zbioru ASCII &#8212; litery <i>d<\/i>, przedstawiany jest przez pythonow\u0105 funkcj\u0119 <i>repr()<\/i> po prostu jako <tt>'d'<\/tt> a nie w postaci wy-escape-owanej <tt>'\\x64'<\/tt>), w kodowaniu <i>latin2<\/i> b\u0119dzie to <tt>'\\xb3\\xf3d\\xbc'<\/tt> (4 bajty: 0xb3, 0xf3, 0x64, 0xbc), w kodowaniu <i>utf-8<\/i> b\u0119dzie to '\\xc5\\x82\\xc3\\xb3d\\xc5\\xba&#8217; (6 bajt\u00f3w: 0xc5, 0x82, 0xc3, 0xb3, 0x64, 0xc5, 0xba). Informacja o kodowaniu nie jest zawarta w samych danych &#8212; dla komputera jest to po prostu ci\u0105g bajt\u00f3w (liczb ca\u0142kowitych od 0 do 255) i tyle (a wi\u0119c to Ty jako programista musisz wiedzie\u0107, jakiego u\u017cy\u0107 kodowania do ich interpretacji).<br \/>\n<b>Uwaga:<\/b> je\u017celi w kodzie \u017ar\u00f3d\u0142owym swojego programu umie\u015bcisz litera\u0142 napisu typu <i>str<\/i> u\u017cywaj\u0105c znak\u00f3w spoza ASCII, np. &#8222;\u0142\u00f3d\u017a&#8221; (a nie np. &#8222;\\xc5\\x82\\xc3\\xb3d\\xc5\\xba&#8221;), spos\u00f3b jego interpretacji przez Pythona zale\u017cy od 2 rzeczy: <i>a)<\/i> jakiego kodowania u\u017cywa Tw\u00f3j edytor tekstu; <i>b)<\/i> jakie kodowanie jest zadeklarowane na pocz\u0105tku Twojego pliku \u017ar\u00f3d\u0142owego (deklaracja <tt># -*- coding: ... -*-<\/tt>; jej brak oznacza domy\u015blne kodowanie: <i>ascii<\/i>) &#8212; musisz zadba\u0107, aby kodowania <i>a<\/i> i <i>b<\/i> by\u0142y <b>zgodne<\/b> (inaczej nastanie taki ba\u0142agan, \u017ce sie nie po\u0142apiesz); je\u017celi np. oba (<i>a<\/i> i <i>b<\/i>) b\u0119d\u0105 <i>utf-8<\/i>, to litera\u0142 &#8222;\u0142\u00f3d\u017a&#8221; b\u0119dzie r\u00f3wnoznaczny litera\u0142owi &#8222;\\xc5\\x82\\xc3\\xb3d\\xc5\\xba&#8221;.<\/p>\n<p>2. Obiekt typu <i>unicode<\/i> czyli <b>ci\u0105g znak\u00f3w<\/b> (m\u00f3wi\u0105c \u015bci\u015blej: <i>code point\u00f3w<\/i> czyli abstrakcyjnych warto\u015bci liczbowych od 0 do 1114111 odpowiadaj\u0105cych wg standardu <a href=\"http:\/\/www.unicode.org\/standard\/WhatIsUnicode.html\" target=\"_blank\">Unicode<\/a> poszczeg\u00f3lnm znakom) &#8212; np. s\u0142owo <i>\u0142\u00f3d\u017a<\/i> b\u0119dzie mia\u0142o zawsze tak\u0105 sam\u0105 posta\u0107: u&#8217;\\u0142\\xf3d\\u017a&#8217; (czyli cztery znaki o kodach [<i>code-pointach<\/i>]: 0x142, 0xf3, 0x64, 0x17a). Dop\u00f3ki operujesz obiektami typu <i>unicode<\/i>, w og\u00f3le <b>nie ma tematu<\/b> takiego czy innego <i>kodowania<\/i>.<br \/>\n<b>Uwaga:<\/b> je\u017celi w kodzie \u017ar\u00f3d\u0142owym swojego programu umie\u015bcisz litera\u0142 napisu typu <i>unicode<\/i> u\u017cywaj\u0105c znak\u00f3w spoza ASCII, np. u&#8221;\u0142\u00f3d\u017a&#8221;, spos\u00f3b jego interpretacji przez Pythona jest jednoznaczny (litera\u0142 u&#8221;\u0142\u00f3d\u017a&#8221; jest r\u00f3wnoznaczny litera\u0142owi u&#8221;\\u0142\\xf3d\\u017a&#8221;), pod warunkiem \u017ce kodowanie u\u017cywane przez Tw\u00f3j edytor tekstu jest <b>zgodne<\/b> z kodowaniem zadaklarowanym na pocz\u0105tku Twojego pliku \u017ar\u00f3d\u0142owego (deklaracj\u0105 <tt># -*- coding: ... -*-<\/tt>; jej brak oznacza domy\u015blne kodowanie: <i>ascii<\/i>).<\/p>\n<p>Zasadniczo w 99% przypadk\u00f3w do danych tekstowych nale\u017cy u\u017cywa\u0107:<\/p>\n<ul>\n<li>typu <i>str<\/i> &#8212; tylko na wej\u015bciu i na wyj\u015bciu Twojego programu (pliki, komunikacja sieciowa itp.);<\/li>\n<li>typu <i>unicode<\/i> &#8212; wewn\u0105trz ca\u0142ego Twojego programu.<\/li>\n<\/ul>\n<p>Np. zak\u0142adaj\u0105c, \u017ce w zmiennej <i>bajty_z_sieci<\/i> masz wyraz <i>\u0142\u00f3d\u017a<\/i> zakodowany <i>utf-8<\/i>, a w zmiennej <i>bajty_z_pliku<\/i> &#8212; ten sam wyraz zakodowany <i>windows-1250<\/i>&#8230;<\/p>\n<div class=\"codeheader\">Kod<\/div>\n<pre class=\"geshi\">&gt;&gt;&gt; bajty_z_sieci\n'\\xc5\\x82\\xc3\\xb3d\\xc5\\xba'\n&gt;&gt;&gt; bajty_z_pliku\n'\\xb3\\xf3d\\x9f'\n&gt;&gt;&gt; bajty_z_sieci == bajty_z_pliku\nFalse\n<\/pre>\n<p><b>Odkodowujemy<\/b> [ang. <i>decode<\/i>] oba napisy z postaci bajtowej (<i>str<\/i>), z u\u017cyciem odpowiednich kodowa\u0144, do postaci <i>unicode<\/i>&#8230;<\/p>\n<div class=\"codeheader\">Kod<\/div>\n<pre class=\"geshi\">&gt;&gt;&gt; napis_z_sieci = bajty_z_sieci.decode('utf-8')\n&gt;&gt;&gt; napis_z_pliku = bajty_z_pliku.decode('windows-1250')<\/pre>\n<p>&#8230;i jak widzimy, oba zawieraj\u0105 ten sam wyraz:<\/p>\n<div class=\"codeheader\">Kod<\/div>\n<pre class=\"geshi\">&gt;&gt;&gt; napis_z_sieci\nu'\\u0142\\xf3d\\u017a'\n&gt;&gt;&gt; napis_z_pliku\nu'\\u0142\\xf3d\\u017a'\n&gt;&gt;&gt; napis_z_sieci == napis_z_pliku\nTrue<\/pre>\n<p>Maj\u0105c napis w postaci <i>unicode<\/i> mo\u017cemy wygodnie operowa\u0107 na nim jako na tek\u015bcie, np.:<\/p>\n<div class=\"codeheader\">Kod<\/div>\n<pre class=\"geshi\">&gt;&gt;&gt; napis_wynikowy = napis_z_sieci.upper()\n&gt;&gt;&gt; napis_wynikowy\nu'\\u0141\\xd3D\\u0179'\n&gt;&gt;&gt; print napis_wynikowy\n\u0141\u00d3D\u0179<\/pre>\n<p>Je\u017celi chcemy zapisa\u0107 dane tekstowe do pliku lub wys\u0142a\u0107 przez sie\u0107, musimy przekonwertowa\u0107 je z postaci <i>unicode<\/i> do postaci bajtowej czyli <i>str<\/i> (czyli <b>zakodowa\u0107<\/b> [ang. <i>encode<\/i>] z u\u017cyciem jakiego\u015b kodowania, np. <i>utf-8<\/i>):<\/p>\n<div class=\"codeheader\">Kod<\/div>\n<pre class=\"geshi\">&gt;&gt;&gt; bajty_wynikowe = napis_wynikowy.encode('utf-8')<\/pre>\n<p>Teraz mo\u017cemy np. zapisa\u0107 te dane do pliku:<\/p>\n<div class=\"codeheader\">Kod<\/div>\n<pre class=\"geshi\">&gt;&gt;&gt; with open('dane-wynikowe.txt', 'w') as f:\n... \u00a0 \u00a0 \u00a0 \u00a0 f.write(bajty_wynikowe)\n...<\/pre>\n<p>PS. [Edit] Oczywi\u015bcie nie ka\u017cde kodowanie obejmuje wszystkie mo\u017cliwe znaki.<\/p>\n<p>We\u017amy 2 znaki spoza ASCII: francusk\u0105 liter\u0119 <i>\u00e8<\/i> (<tt>u'\\xe8'<\/tt>) i polsk\u0105 liter\u0119 <i>\u0119<\/i> (<tt>u'\\u0119'<\/tt>)&#8230;<\/p>\n<p>Np. kodowanie <i>latin1<\/i> (znane te\u017c jako <i>iso-8859-1<\/i>) obejmuje <i>\u00e8<\/i>, ale nie <i>\u0119<\/i>:<\/p>\n<div class=\"codeheader\">Kod:<\/div>\n<div class=\"code\">&gt;&gt;&gt; u&#8217;\\xe8&#8242;.encode(&#8217;latin1&#8242;)<br \/>\n'\\xe8&#8242;<br \/>\n&gt;&gt;&gt; u&#8217;\\u0119&#8242;.encode(&#8217;latin1&#8242;)<br \/>\nTraceback (most recent call last):<br \/>\nFile &#8222;&lt;stdin&gt;&#8221;, line 1, in &lt;module&gt;<br \/>\nUnicodeEncodeError: 'latin-1&#8242; codec can&#8217;t encode character u&#8217;\\u0119&#8242; in position 0: ordinal not in range(256)<\/div>\n<p>Z kolei kodowania <i>latin2<\/i> (znane te\u017c jako <i>iso-8859-2<\/i>) i <i>windows-1250<\/i> obejmuj\u0105 <i>\u0119<\/i>, ale nie <i>\u00e8<\/i>:<\/p>\n<div class=\"codeheader\">Kod:<\/div>\n<div class=\"code\">&gt;&gt;&gt; u&#8217;\\xe8&#8242;.encode(&#8217;latin2&#8242;)<br \/>\nTraceback (most recent call last):<br \/>\nFile &#8222;&lt;stdin&gt;&#8221;, line 1, in &lt;module&gt;<br \/>\nFile &#8222;\/home\/zuo\/.virtualenvs\/unittest_expander\/lib\/python2.7\/encodings\/iso8859_2.py&#8221;, line 12, in encode<br \/>\nreturn codecs.charmap_encode(input,errors,encoding_table)<br \/>\nUnicodeEncodeError: 'charmap&#8217; codec can&#8217;t encode character u&#8217;\\xe8&#8242; in position 0: character maps to &lt;undefined&gt;<br \/>\n&gt;&gt;&gt; u&#8217;\\u0119&#8242;.encode(&#8217;latin2&#8242;)<br \/>\n'\\xea&#8217;<\/div>\n<p>Oba wy\u017cej wymienione znaki (i wiele, wiele innych &#8212; wszystkie reprezentowalne z u\u017cyciem <i>unicode<\/i>) obejmuje kodowanie <i>utf-8<\/i>:<\/p>\n<div class=\"codeheader\">Kod:<\/div>\n<div class=\"code\">&gt;&gt;&gt; u&#8217;\\xe8&#8242;.encode(&#8217;utf-8&#8242;)<br \/>\n'\\xc3\\xa8&#8242;<br \/>\n&gt;&gt;&gt; u&#8217;\\u0119&#8242;.encode(&#8217;utf-8&#8242;)<br \/>\n'\\xc4\\x99&#8242;<\/div>\n<p>Za\u015b kodowanie <i>ascii<\/i> (domy\u015blne w Pythonie 2.x) nie obejmuje \u017cadnego z tych\u017ce 2 znak\u00f3w, bo jego zakres to jedynie 128 znak\u00f3w b\u0119d\u0105cych wsp\u00f3lnym podzbiorem wszystkich wy\u017cej wymienionych kodowa\u0144&#8230;<\/p>\n<div class=\"codeheader\">Kod:<\/div>\n<div class=\"code\">&gt;&gt;&gt; u&#8217;\\xe8&#8242;.encode(&#8217;ascii&#8217;)<br \/>\nTraceback (most recent call last):<br \/>\nFile &#8222;&lt;stdin&gt;&#8221;, line 1, in &lt;module&gt;<br \/>\nUnicodeEncodeError: 'ascii&#8217; codec can&#8217;t encode character u&#8217;\\xe8&#8242; in position 0: ordinal not in range(128)<br \/>\n&gt;&gt;&gt; u&#8217;\\u0119&#8242;.encode(&#8217;ascii&#8217;)<br \/>\nTraceback (most recent call last):<br \/>\nFile &#8222;&lt;stdin&gt;&#8221;, line 1, in &lt;module&gt;<br \/>\nUnicodeEncodeError: 'ascii&#8217; codec can&#8217;t encode character u&#8217;\\u0119&#8242; in position 0: ordinal not in range(128)<\/div>\n","protected":false},"excerpt":{"rendered":"<p class=\"excerpt\">\u017ar\u00f3d\u0142o:\u00a0https:\/\/pl.python.org\/forum\/index.php?topic=5190.0 Dane tekstowe w Pythonie 2.x (bo z kontekstu rozumiem, \u017ce o Pythonie 2.x tu mowa) mog\u0105 by\u0107 reprezentowane na dwa sposoby: 1. Obiekt typu str czyli ci\u0105g bajt\u00f3w (czyli posta\u0107, w jakiej dane wyst\u0119puj\u0105 w plikach na dysku, w komunikacji przez sie\u0107 itp.) &#8212; np. s\u0142owo \u0142\u00f3d\u017a b\u0119dzie mia\u0142o r\u00f3\u017cn\u0105 posta\u0107 w zale\u017cno\u015bci od&hellip;<\/p>\n<p class=\"more-link-p\"><a class=\"more-link\" href=\"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/2016\/12\/28\/kodowanie-danych-tekstowych-w-pythonie\/\">Read more &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[77],"class_list":["post-1614","post","type-post","status-publish","format-standard","hentry","category-bez-kategorii","tag-python"],"_links":{"self":[{"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/posts\/1614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/comments?post=1614"}],"version-history":[{"count":0,"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/posts\/1614\/revisions"}],"wp:attachment":[{"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/media?parent=1614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/categories?post=1614"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/u239160.webh.me\/jakisproblem.pl\/index.php\/wp-json\/wp\/v2\/tags?post=1614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}