<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Jaros&#322;aw Zabie&#322;&#322;o - BLOG: MySQLdb &amp; client encoding</title>
    <link>http://blog.zabiello.com/articles/2006/08/16/mysqldb-client-encoding</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>MySQLdb &amp;amp; client encoding</title>
      <description>&lt;p&gt;[vide: &lt;a href="http://blog.zabiello.com/pages/en/mysqldb-client-encoding"&gt;English version&lt;/a&gt;]&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://sourceforge.net/projects/mysql-python"&gt;MySQLdb&lt;/a&gt; to g&#322;&#243;wna biblioteka dla Pythona obs&#322;uguj&#261;ca baz&#281; MySQL. Baza ta (od werseji 4.1 wzwy&#380;) ma wbudowany wygodny mechanizm translacji znak&#243;w jakie maj&#261; by&#263; wy&#347;wietlane dla klienta. Oczywi&#347;cie, nale&#380;y za&#322;o&#380;y&#263;, &#380;e natywnym formatem danych dla bazy to &lt;span class="caps"&gt;UTF&lt;/span&gt;-8. Za pomoc&#261; prostej kwerendy (SET &lt;span class="caps"&gt;NAMES&lt;/span&gt; latin2) mo&#380;na wymusi&#263; aby wszelkie napisy by&#322;y wypluwane do klienta w wybranym formacie (tu: iso-8859-2).&lt;/p&gt;


	&lt;p&gt;Ostatnio, przy okazji pracy z &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt;, przyjrza&#322;em si&#281; bardzo ciekawemu projektowi: &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;. Wszystko wskazuje na to, &#380;e &lt;a href="http://www.sqlobject.org/"&gt;SQLObject&lt;/a&gt; odejdzie do lamusa (tym bardziej &#380;e jego tw&#243;rca co&#347; go porzuci&#322; i planuje stworzy&#263; nowy SQLObject2). &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt; jest nie tylko znacznie pote&#380;niejszym &lt;a href="http://en.wikipedia.org/wiki/Object-relationship_modeling"&gt;&lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/a&gt;, ale ma tak&#380;e znacznie lepsz&#261; dokumentacj&#281; ni&#380; SQLObject &amp;#8211; ok. 117 stron samego tylko &lt;a href="http://www.sqlalchemy.org/docs/"&gt;manuala&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Jedyny problem, jakie to typowe, to brak czytelnej opcji translacji polskich znak&#243;w. Podobny problem swego czasu znalaz&#322;em w Django (wys&#322;a&#322;em patcha i to poprawili dodaj&#261;c na sztywno &amp;#8220;SET &lt;span class="caps"&gt;NAMES&lt;/span&gt; utf8&amp;#8221;) W wypadku SQLAlchemy nie ma opcji do definicji kodowania po stronie klienta. Manual wspomina tylko o ustawieniu kodowania dla bazy, a to nie to samo. Okazuje, si&#281;, &#380;e rozwi&#261;zanie jest bardzo proste. Podczas tworzenia po&#322;&#261;czenia do bazy wystarczy u&#380;y&#263; dodatkowych parametr&#243;w. Nie ma potrzeby bawienia si&#281; w &#380;adne kwerendy &amp;#8220;SET &lt;span class="caps"&gt;NAMES&lt;/span&gt;&amp;#8221;. Owe parametry to &lt;strong&gt;use_unicode&lt;/strong&gt; i &lt;strong&gt;charset&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;MySQLdb&lt;/span&gt;
&lt;span class="ident"&gt;conn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;MySQLdb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;connect&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;root&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="ident"&gt;passwd&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="ident"&gt;db&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="ident"&gt;use_unicode&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;False&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
    &lt;span class="ident"&gt;charset&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;cp1250&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W powy&#380;szym wypadku, MySQL b&#281;dzie zak&#322;ada&#322; &#380;e klient ma odebra&#263; teksty w formacie string&#243;w cp1250. Za&#347; w wypadku u&#380;ycia &amp;#8220;use_unicode=True&amp;#8221; zwracane b&#281;d&#261; &#347;liczne obiekty unicodowe! Przyk&#322;adowy plik konfiguracyjny dla Pylonsa korzystaj&#261;cego z SQLAlchemy (config/&lt;i&gt;init&lt;/i&gt;.py) mo&#380;e zatem wygl&#261;da&#263; np. tak:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;sqlalchemy&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;
&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;sqlalchemy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pool&lt;/span&gt; &lt;span class="ident"&gt;as&lt;/span&gt; &lt;span class="ident"&gt;pool&lt;/span&gt;
&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;MySQLdb&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;getconn&lt;/span&gt;&lt;span class="punct"&gt;():&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;MySQLdb&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;connect&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
        &lt;span class="ident"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;root&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
        &lt;span class="ident"&gt;passwd&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
        &lt;span class="ident"&gt;db&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
        &lt;span class="ident"&gt;use_unicode&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;False&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; 
        &lt;span class="ident"&gt;charset&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;utf8&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;

&lt;span class="ident"&gt;db&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;create_engine&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;mysql://root:@localhost/test&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="ident"&gt;pool&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;pool&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;QueuePool&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;getconn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;pool_size&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;20&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;max_overflow&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;40&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; 
    &lt;span class="ident"&gt;strategy&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;threadlocal&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;span class="ident"&gt;metadata&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;BoundMetaData&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;db&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;test_table&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Table&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;test&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;metadata&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;autoload&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Test(object):&lt;/span&gt;  
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;__str__&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;  
        &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt;  

&lt;span class="ident"&gt;test_mapper&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;mapper&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;test_table&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W powy&#380;szym przyk&#322;adzie, wymusi&#322;em kodowanie utf8 dla klienta oraz po&#322;&#261;czenie z baz&#261; dzia&#322;a&#263; b&#281;dzie w puli 20-40 w&#261;tk&#243;w. W&#322;a&#347;nie tego mi brakuje w Django: pracy wielow&#261;tkowej, bo zu&#380;ywa ona mniej pami&#281;ci. W/w model mo&#380;na u&#380;y&#263; w kontrolerze Pylons (controllers/home.py) np. tak:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;myproject&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;lib&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;base&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;myproject&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;models&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;HomeController(BaseController):&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;        
      &lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;rows&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;select&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="ident"&gt;test_table&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;test_table&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;c&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]).&lt;/span&gt;&lt;span class="ident"&gt;execute&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
      &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;render_response&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/home.myt&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 16 Aug 2006 01:28:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:a7940b1d-4893-4e0a-b1aa-60d91a5a1207</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/08/16/mysqldb-client-encoding</link>
      <category>Databases</category>
      <category>Pylons</category>
      <category>Python</category>
      <category>mysql</category>
      <category>pylons</category>
      <category>python</category>
      <category>sqlalchemy</category>
    </item>
    <item>
      <title>"MySQLdb &amp; client encoding" by climbus</title>
      <description>&lt;p&gt;chyba jednak nie. ustawia na true je&#380;eli jest charset ale p&#243;&#378;niej nadpisuje to je&#380;eli jest opcja use_unicode&lt;/p&gt;</description>
      <pubDate>Mon, 05 Mar 2007 09:47:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:64437dcc-7b2b-425e-91f0-7aa21328e660</guid>
      <link>http://blog.zabiello.com/articles/2006/08/16/mysqldb-client-encoding#comment-573</link>
    </item>
    <item>
      <title>"MySQLdb &amp; client encoding" by climbus</title>
      <description>&lt;p&gt;z tego co wyczyta&#322;em z kadu mysqldb je&#380;eli jest ustawiony charset mysqldb ustawia use_unicode na true&lt;/p&gt;</description>
      <pubDate>Mon, 05 Mar 2007 08:44:28 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:c543795f-8421-4d6e-8ace-e83c2cdf4d4f</guid>
      <link>http://blog.zabiello.com/articles/2006/08/16/mysqldb-client-encoding#comment-572</link>
    </item>
    <item>
      <title>"MySQLdb &amp; client encoding" by rsz</title>
      <description>&lt;p&gt;Dok&#322;adnie to samo (na sztywno SET NAMES utf8) musieli&#347;my whackowa&#263; do SQLObjecta. Nie ma to, jak dobrze zaprojektowany soft.&lt;/p&gt;</description>
      <pubDate>Thu, 17 Aug 2006 09:08:45 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:ed022b7e-ade0-4268-bdae-3b0a08b96933</guid>
      <link>http://blog.zabiello.com/articles/2006/08/16/mysqldb-client-encoding#comment-187</link>
    </item>
    <item>
      <title>"MySQLdb &amp; client encoding" by Riklaunim riklaunim@gmail.com</title>
      <description>&lt;p&gt;wszystko fajnie tylko dlaczego tw&#243;rcy pylons tak olewaj&#261; dokumentacj&#281;? Czy my&#347;l&#261; &#380;e puszczenie linka do myghty i sqlalchemy za&#322;atwi spraw&#281;?
Zwr&#243;ci&#322;em im na to uwag&#281; i sko&#324;czy&#322;o si&#281; na s&#322;owach &amp;#8220;poprawy&amp;#8221; :|&lt;/p&gt;</description>
      <pubDate>Wed, 16 Aug 2006 19:40:12 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:5d5b3978-6ffc-4cb9-892d-64284a883495</guid>
      <link>http://blog.zabiello.com/articles/2006/08/16/mysqldb-client-encoding#comment-186</link>
    </item>
  </channel>
</rss>
