%% Presentation about Unicode in Python

%% Some useful variations of the document class
%%\documentclass[ignorenonframetext,draft]{beamer}
%%\documentclass[ignorenonframetext,handout]{beamer}
\documentclass[]{beamer}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{fancyvrb}
\usepackage{color}
\usepackage{eurosym}
\mode<presentation>{\usetheme{Copenhagen}}
\title{Unicode in Python, demystifiziert}
\author{Marek~Kubica}
\date{18.~September~2008}

%% get rid of navigation symbols
\beamertemplatenavigationsymbolsempty
%%\setbeamertemplate{navigation symbols}{}

%% include color commands
\input{colordefs.tex}

\begin{document}

\frame{\titlepage}

\AtBeginSection[]{
  \begin{frame}
    \frametitle{\insertsection}
    \tableofcontents[currentsection]
  \end{frame}
}

\section{Das Problem -- Internationalisierung}

\subsection{Voraussetzungen für Internationalisierung}

\begin{frame}[fragile]
  \frametitle{Was heißt das?}
  \begin{block}{Der Fehler}
    \begin{Verbatim}
UnicodeDecodeError: 'ascii' codec
can't decode byte 0xc4 in position
10: ordinal not in range(128)
    \end{Verbatim}
  \end{block}
  \pause
  \begin{itemize}
    \item Noch nie diese Exception gesehen?
    \item Doch gesehen und irgendwie korrigiert?
    \item Das ist ein \emph{seltsamer} Fehler
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Was gibt es für Anforderungen?}
  \begin{itemize}
    \item Sprachen außer Englisch unterstützen
    \item Fremde Module nutzen
    \item \emph{beliebige} Texteingaben akzeptieren
      \pause
      \begin{itemize}
        \item nie wieder \emph{ue}, \emph{oe} etc.
	\item nie wieder Akzente weglassen
	\item nie wieder Namen transkribieren
	\item nie wieder komische Zeichen auf dem Bildschirm
      \end{itemize}
  \end{itemize}
\end{frame}

\subsection{Anwendungsgebiete}

\begin{frame}
  \frametitle{Web-Applikationen}
  \includegraphics[height=13cm]{text-lifecycle-web.png}
\end{frame}

\begin{frame}
  \frametitle{Datenbankinteraktion}
  \includegraphics[height=13cm]{text-lifecycle-db.png}
\end{frame}

\begin{frame}
  \frametitle{Konsolenprogramm}
  \includegraphics[height=13cm]{text-lifecycle-script.png}
\end{frame}

\begin{frame}
  \frametitle{Die Lösung}
  \begin{block}{Unicode}
    \includegraphics{i_unicode}
    \begin{itemize}
      \item An Unicode führt kein Weg vorbei
      \item Man kann es nicht mehr ignorieren
    \end{itemize}
  \end{block}
\end{frame}

\subsection{Unicode-Spielereien}

\begin{frame}
  \frametitle{Unicodekarte}
  \begin{block}{Ian Alberts Unicodekarte}
    \begin{itemize}
      \item er hat sich die gesamte Unicodekarte ausgedruckt
      \item 1.114.112 Codepoints
      \item 1,8 mal 3,7 Meter
      \item 22.017 * 42.807 Pixel
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{Unicodekarte}
  \includegraphics[height=6.7cm]{unichart-printed}
\end{frame}

\begin{frame}
  \frametitle{Unicodekarte 50\%}
  \includegraphics[height=6.7cm]{unichart-50}
\end{frame}

\begin{frame}
  \frametitle{Unicodekarte 100\%}
  \includegraphics[height=6.7cm]{unichart-100}
\end{frame}

\section{Mit Unicode arbeiten}

\subsection{Am Anfang war eine Datei}

\begin{frame}[fragile]
  \frametitle{Öffnen wir eine UTF-8 kodierte Datei}
  \begin{block}{Karl Müller}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]f @PYbf[=] @PYaY[open](@PYad[']@PYad[/tmp/karl_utf8.txt]@PYad['], @PYad[']@PYad[r]@PYad['])
@PYaP[>>> ]karl_utf8 @PYbf[=] f@PYbf[.]read()
@PYaP[>>> ]karl_utf8
@PYaa['Karl M\xc3\xbcller']
    \end{Verbatim}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Was ist es denn?}
  \begin{block}{Im Interpreter}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]karl_utf8
@PYaa['Karl M\xc3\xbcller']
@PYaP[>>> ]@PYaY[type](karl_utf8)
@PYaa[<type 'str'>]
    \end{Verbatim}
  \end{block}
  \pause
  \begin{itemize}
    \item ein String aus Bytes
    \item 1 Byte = 8 Bits
    \item ein Bit ist entweder ``0'' oder ``1''
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Was ist es denn?}
  \begin{block}{Im Interpreter}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaa['Karl M\xc3\xbcller']
    \end{Verbatim}
  \end{block}
  \pause
  \begin{itemize}
    \item dieser String ist UTF-8-kodiert
    \item Ein Zeichensatz bezeichnet die Regeln die Zahlen Zeichen (Buchstaben)
      zuordnet
    \item Das ü wird durch zwei Bytes repräsentiert
    \item Andere Zeichensätze können das ü anders darstellen
    \item Die Python Stdlib unterstützt über 100 Zeichensätze
  \end{itemize}
\end{frame}

\subsection{ASCII}

\begin{frame}
  \frametitle{ASCII}
  Der wohl bekannteste Zeichensatz
  \begin{block}{Unser Beispiel}
    \begin{tabular}{| l || l | l | l | l |}
      \hline
      Zeichen & K & a & r & l \\
      \hline
      Hexadezimal & \textbackslash{}x4b & \textbackslash{}x61 & 
        \textbackslash{}x72 & \textbackslash{}x6c \\
      \hline
      Dezimal & 75 & 97 & 114 & 108 \\
      \hline
    \end{tabular}
  \end{block}
  \begin{itemize}
    \item UTF-8 ist eine Erweiterung von ASCII
    \item \emph{1963} als ``\emph{American} Standard Code for Information
      Exchange''
    \item jedes Zeichen ist 1 Byte lang
    \item nutzt 7 Bit, also 2\textsuperscript{7} = 128 Zeichen möglich
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{ASCII, fortgesetzt}
  \begin{block}{Der Nachname}
    \begin{tabular}{| l || l | l | l | l | l | l |}
      \hline
      Zeichen & M & ü & l & l & e & r \\
      \hline
      Hexadezimal & \textbackslash{}x4d & gibt's nicht & 
        \textbackslash{}x6c & \textbackslash{}e6c &
	\textbackslash{}x65 & \textbackslash{}x72 \\
      \hline
      Dezimal & 77 & gibt's nicht & 108 & 108 & 101 & 114\\
      \hline
    \end{tabular}
  \end{block}
  Daraus folgt dann...
\end{frame}

\begin{frame}
  \frametitle{ü kann nicht in ASCII kodiert werden}
  \begin{center}
    \includegraphics[height=6.7cm]{doh}
  \end{center}
\end{frame}

\subsection{Was bietet Python in der Hinsicht}

\begin{frame}
  \frametitle{Eingebaute String-Datentypen}
  \begin{block}{Python 2.x}
    \begin{itemize}
      \item \texttt{<type 'basestring'>}
        \begin{itemize}
	  \item \texttt{<type 'str'>}
	  \item \texttt{<type 'unicode'>}
	\end{itemize}
    \end{itemize}
  \end{block}
  \begin{block}{Python 3.0}
    \begin{itemize}
      \item nur noch \texttt{<type 'str'>}
      \item verhält sich aber wie \texttt{<type 'unicode'>}
      \pause
      \item \texttt{<type 'bytes'>} gibt es nun zusätzlich
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{Wichtige Methoden}
  \begin{block}{str.decode(encoding)}
    Von \texttt{<type 'str'>} zu \texttt{<type 'unicode'>} konvertieren.
  \end{block}
  \begin{block}{unicode.encode(encoding)}
    Von \texttt{<type 'unicode'>} zu \texttt{<type 'str'>} konvertieren.
  \end{block}
\end{frame}

\subsection{Warum überhaupt Unicode}

\begin{frame}[fragile]
  \frametitle{Das Problem}
  Kann mein Text nicht einfach enkodiert bleiben?
  \begin{block}{Interpreter}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]karl_utf8
@PYaa['Karl M\xc3\xbcller']
@PYaP[>>> ]@PYaY[len](karl_utf8)
@PYaa[12]
@PYaP[>>> ]karl_utf8@lb[]@PYax[7]@rb[]
@PYaa['\xbc']
    \end{Verbatim}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Unicode ist unproblematischer}
  \begin{block}{Interpreter}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]karl_utf8
@PYaa['Karl M\xc3\xbcller']
@PYaP[>>> ]karl_uni @PYbf[=] karl_utf8@PYbf[.]decode(@PYad[']@PYad[utf-8]@PYad['])
@PYaP[>>> ]karl_uni
@PYaa[u'Karl M\xfcller']
@PYaP[>>> ]@PYaY[type](karl_uni)
@PYaa[<type 'unicode'>]
@PYaP[>>> ]@PYaY[len](karl_uni)
@PYaa[11]
@PYaP[>>> ]karl_uni@lb[]@PYax[7]@rb[]
@PYaa[u'\xfc']
    \end{Verbatim}
  \end{block}
\end{frame}

\section{Über Unicode}

\subsection{Eintauchen in Unicode}

\begin{frame}[fragile]
  \frametitle{Unicode, was soll das sein?}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaa[u'Karl M\xfcller']
  \end{Verbatim}
  \begin{itemize}
    \item eine Art Text ohne Bytewerte auszudrücken
    \item eine eindeutige Zahl (Codepoint) für jedes Zeichen jeder Sprache
    \item unterstützt nahezu alle Sprachen die heutzutage geschrieben werden
    \item definiert über 1 Million Codepoints
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Unicode ist ein Konzept}
  \begin{tabular}{| l | l |}
    \hline
    Buchstabe & Unicode Codepoint \\
    \hline
    ü & \textbackslash{}u00fc = \textbackslash{}xfc \\
    \hline
    \EUR & \textbackslash{}u20ac \\
    \hline
  \end{tabular}
  \begin{itemize}
    \item Man kann ein Konzept nicht auf Festplatte speichern (abstrakt)
    \item Man muss es also vorher enkodieren (konkret)
  \end{itemize}
  \begin{tabular}{| l | l | l | l | l |}
    \hline
    Buchstabe & UTF-8 & UTF-16 & Latin-1 & Latin-9 \\
    \hline
    ü & \textbackslash{}xc3\textbackslash{}xbc &
      \textbackslash{}xfc\textbackslash{}x00 &
      \textbackslash{}xfc & \textbackslash{}xfc \\
    \hline
    \EUR & \textbackslash{}xe2\textbackslash{}x82\textbackslash{}xac &
      \textbackslash{}xac\textbackslash{}x20 &
      - & \textbackslash{}xa4 \\
    \hline
  \end{tabular}
\end{frame}

\subsection{Zeichensätze für Unicode}

\begin{frame}
  \frametitle{Notwendig für das Verständnis von Unicode}
  \begin{center}
    \Large{\textbf{UTF-8 IST NICHT GLEICH UNICODE}}
  \end{center}
  \pause
  \begin{itemize}
    \item genausowenig wie UTF-16, UTF-32 gleich Unicode sind
    \item Microsoft nennt UTF-16 Unicode
    \item IBM verwechselt manchmal UTF mit Unicode (``Unicode encoded'')
    \pause
    \item dennoch irreführend bis \emph{falsch}
  \end{itemize}
\end{frame}


\begin{frame}[fragile]
  \frametitle{Unicode Transformation Format}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]ab @PYbf[=] @PYaY[unicode](@PYad[']@PYad[AB]@PYad['])
  \end{Verbatim}
  \begin{block}{UTF-8}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]ab@PYbf[.]encode(@PYad[']@PYad[utf-8]@PYad['])
@PYaa['AB']
    \end{Verbatim}
    \begin{itemize}
      \item nutzt variable Byteanzahl
      \item 1 bis 4 Bytes pro Codepoint (\emph{8} bis 32 Bit)
      \item erste 128 Zeichen identisch mit ASCII
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Unicode Transformation Format}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]ab @PYbf[=] @PYaY[unicode](@PYad[']@PYad[AB]@PYad['])
  \end{Verbatim}
  \begin{block}{UTF-16}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]ab@PYbf[.]encode(@PYad[']@PYad[utf-16]@PYad['])
@PYaa['\xff\xfeA\x00B\x00']
    \end{Verbatim}
    \begin{itemize}
      \item nutzt variable Byteanzahl
      \item 2 bis 4 Bytes pro Codepoint (\emph{16} bis 32 Bit)
      \item für Sprachen deren Zeichen 2 Byte lang sind gut geeignet
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{Unicode Transformation Format}
  \begin{block}{UTF-32}
    \begin{itemize}
      \item feste Byteanzahl, daher schnell zu verarbeiten
      \item 4 Bytes pro Codepoint (\emph{32} Bit)
      \item von Python 2.x nicht unterstützt
    \end{itemize}
  \end{block}
\end{frame}

\subsection{Nach Unicode und zurück}

\begin{frame}
  \frametitle{Text in Unicode dekodieren}
  \begin{itemize}
    \item es läuft meist automatisch
    \item passiert oft in externen Modulen
    \item Python versucht es zu dekodieren
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Python-Magie aufgedeckt}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]karl_uni @PYbf[=] @PYad[u']@PYad[Karl Müller]@PYad[']
@PYaP[>>> ]karl_uni
@PYaa[u'Karl M\xfcller']
@PYaP[>>> ]f @PYbf[=] @PYaY[open](@PYad[']@PYad[/tmp/karl.txt]@PYad['], @PYad[']@PYad[w]@PYad['])
@PYaP[>>> ]f@PYbf[.]write(karl_uni)
@PYaC[Traceback (most recent call last):]
  File @PYaY[``<stdin>''], line @PYaR[1], in <module>
@PYaO[UnicodeEncodeError: 'ascii' codec can't encode character]
@PYaO[u'\xfc' in position 6]: ordinal not in range(128)
  \end{Verbatim}      
\end{frame}

\begin{frame}
  \frametitle{Schluck!}
  \begin{center}
    \Large{\textbf{DAS STANDARDENCODING IN PYTHON 2 IST ASCII}}
  \end{center}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Ändere es einfach?!}
  \begin{Verbatim}[commandchars=@\[\]]
sys@PYbf[.]setdefaultencoding(@PYad[']@PYad[utf-8]@PYad['])
  \end{Verbatim}
  \begin{block}{Sowas verwenden?}
    \begin{itemize}
      \item kann ich das nicht einfach in die \texttt{sitecustomize.py} stecken?
      \item Nein!
      \item Der Code wird mit anderen Python-Installationen nicht funktionieren
      \item mehr Aufwand als es wert ist
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{Lösung}
  \begin{enumerate}
    \item Früh in Unicode umwandeln
    \item Überall mit Unicode arbeiten
    \item So spät wie möglich in Bytestrings konvertieren
  \end{enumerate}
\end{frame}

\begin{frame}[fragile]
  \frametitle{1. Früh in Unicode umwandeln}
  Dekodiere nach \texttt{<type 'unicode'>} so früh wie möglich
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]@PYaz[def] @PYaL[to_unicode_or_bust](
@PYaP[... ]        obj, encoding@PYbf[=]@PYad[']@PYad[utf-8]@PYad[']):
@PYaP[... ]    @PYaz[if] @PYaY[isinstance](obj, @PYaY[basestring]):
@PYaP[... ]        @PYaz[if] @PYao[not] @PYaY[isinstance](obj, @PYaY[unicode]):
@PYaP[... ]            obj @PYbf[=] @PYaY[unicode](obj, encoding)
@PYaP[... ]    @PYaz[return] obj
@PYaP[...]
@PYaa[>>>]
  \end{Verbatim}
\end{frame}

\begin{frame}[fragile]
  \frametitle{2. Überall mit Unicode arbeiten}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]to_unicode_or_bust(karl_uni)
@PYaa[u'Karl M\xfcller']
@PYaP[>>> ]to_unicode_or_bust(karl_utf8)
@PYaa[u'Karl M\xfcller']
@PYaP[>>> ]to_unicode_or_bust(@PYax[1234])
@PYaa[1234]
  \end{Verbatim}
\end{frame}

\begin{frame}[fragile]
  \frametitle{3. So spät wie möglich in Bytestrings konvertieren}
  Enkodiere nach \texttt{<type 'str'>} zum speichern auf Festplatte oder zur \textbf{Ausgabe}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]f @PYbf[=] @PYaY[open](@PYad[']@PYad[/tmp/karl_out.txt]@PYad['],@PYad[']@PYad[w]@PYad['])
@PYaP[>>> ]f@PYbf[.]write(karl_uni@PYbf[.]encode(@PYad[']@PYad[utf-8]@PYad[']))
@PYaP[>>> ]f@PYbf[.]close()
  \end{Verbatim}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Abkürzungen}
  \begin{block}{Lesen}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]@PYam[import] @PYaW[codecs]
@PYaP[>>> ]f @PYbf[=] codecs@PYbf[.]open(@PYad[']@PYad[/tmp/karl_utf8.txt]@PYad['], @PYad[']@PYad[r]@PYad['],
@PYaP[... ]                encoding@PYbf[=]@PYad[']@PYad[utf-8]@PYad['])
@PYaP[...]
@PYaP[>>> ]f@PYbf[.]read()
@PYaa[u'Karl M\xfcller']
@PYaP[>>> ]f@PYbf[.]close()
    \end{Verbatim}
  \end{block}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Abkürzungen}
  \begin{block}{Schreiben}
    \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]@PYam[import] @PYaW[codecs]
@PYaP[>>> ]f @PYbf[=] codecs@PYbf[.]open(@PYad[']@PYad[/tmp/karl_utf8.txt]@PYad['], @PYad[']@PYad[w]@PYad['],
@PYaP[... ]                encoding@PYbf[=]@PYad[']@PYad[utf-8]@PYad['])
@PYaP[...]
@PYaP[>>> ]f@PYbf[.]write(karl_uni)
@PYaP[>>> ]f@PYbf[.]close()
    \end{Verbatim}
  \end{block}
  \texttt{<module 'codecs'>} erspart lästiges Umkodieren
\end{frame}

\begin{frame}
  \frametitle{Unicode Inkompatibilität in Python 2}
  \begin{itemize}
    \item einige externe Module unterstützen kein Unicode
      \begin{itemize}
        \item Bugs melden!
      \end{itemize}
    \item einige Module in der Stdlib unterstützen kein Unicode
      \begin{itemize}
        \item \texttt{csv}
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Unicode Workarounds}
  \begin{itemize}
    \item in UTF-8 kodieren, danach wieder nach Unicode konvertieren
    \item Die \texttt{csv}-Dokumentation zeigt wie's geht
  \end{itemize}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]karl_bytes @PYbf[=] karl_uni@PYbf[.]encode(@PYad[']@PYad[utf-8]@PYad['])
@PYaP[>>> ]@PYaE[# verarbeiten]
@PYaP[>>> ]karl_bytes@PYbf[.]decode(@PYad[']@PYad[utf-8]@PYad['])
@PYaa[u'Karl M\xfcller']
  \end{Verbatim}
\end{frame}

\subsection{BOM}

\begin{frame}
  \frametitle{Der/die/das BOM}
  \begin{itemize}
    \item Byte Order Mark
    \item manchmal am Anfang der Dateien
    \item notwendig für Dateien die in UTF-16 und UTF-32 kodiert sind
      \begin{itemize}
        \item Little Endian
        \item Big Endian
      \end{itemize}
    \item UTF-8 BOM sagt nur ``Ich bin UTF-8''
      \begin{itemize}
        \item populär auf Windows
        \item problematisch auf Unix (Shebang)
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{BOM erkennen}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]f @PYbf[=] @PYaY[open](@PYad[']@PYad[/tmp/karl_utf16.txt]@PYad['],@PYad[']@PYad[r]@PYad['])
@PYaP[>>> ]sample @PYbf[=] f@PYbf[.]read(@PYax[4])
@PYaP[>>> ]sample
@PYaa['\xff\xfeI\x00']
  \end{Verbatim}
  \begin{itemize}
    \item BOM kann 2, 3 oder 4 Bytes lang sein
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{BOM erkennen}
  \begin{Verbatim}[commandchars=@\[\]]
@PYaP[>>> ]@PYam[import] @PYaW[codecs]
@PYaP[>>> ](sample@PYbf[.]startswith(codecs@PYbf[.]BOM_UTF16_LE) @PYao[or]
@PYaP[... ] sample@PYbf[.]startswith(codecs@PYbf[.]BOM_UTF16_BE))
@PYaP[...]
@PYaa[True]
@PYaP[>>> ]sample@PYbf[.]startswith(codecs@PYbf[.]BOM_UTF8)
@PYaa[False]
  \end{Verbatim}
\end{frame}

\begin{frame}
  \frametitle{Muss ich das BOM entfernen}
  \begin{itemize}
    \item vielleicht
    \item UTF-16 dekodieren entfernt das BOM automatisch
    \item aber nicht UTF-8
      \begin{itemize}
        \item \emph{es sei denn} man nutzt \texttt{s.decode('utf-8-sig')}
          \begin{itemize}
            \item ab Python 2.5 möglich
          \end{itemize}
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Wie errät man das Encoding?}
  \begin{itemize}
    \item Es gibt keinen verlässlichen Weg, das Encoding zu erraten
    \item BOM kann als Hinweis dienen
    \item \texttt{Content-type}-Header enthält üblicherweise \texttt{charset=...}
    \item Das Modul \texttt{chardet} versucht es
      \begin{itemize}
        \item \url{http://chardet.feedparser.org}
        \item geht wie Mozilla (Firefox) vor
      \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Zusammenfassung der Probleme}
  \begin{itemize}
    \item das Standardencoding von Python 2 ist 'ascii'
    \item Dateien können ein BOM enthalten
    \item nicht alle Python 2-Module in der Stdlib unterstützen Unicode
    \item Man kann das Encoding nicht zuverlässig erraten
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Zusammenfassung der Lösungen}
  \begin{itemize}
    \item Enkodiere früh, Unicode überall einsetzen, dekodiere so spät wie möglich
    \item Wrapper um Libraries schreiben, die kein Unicode können
    \item Unicode in Unittests
    \item Wenn man das Encoding rät ist UTF-8 eine gute Wahl
      \begin{itemize}
        \item Das BOM dient als Indiz
        \item \texttt{chardet.detect} wenn nichts mehr hilft
      \end{itemize}
  \end{itemize}
\end{frame}

\section{Unicode in Python 3}

\begin{frame}
  \frametitle{Unicode in Python 3}
  \begin{itemize}
    \item Unicode wird nun praktikabel!
    \item \texttt{<type 'str'>} ist ein Unicode-Objekt
    \item neuer \texttt{<type 'bytes'>}-Typ
    \item alle Module der Stdlib unterstützen Unicode
    \item keine \texttt{u''text''}-Syntax mehr, dafür \texttt{b''bytes''}
      \begin{itemize}
        \item 2.6: \texttt{from \_\_future\_\_ import unicode\_literals}
      \end{itemize}
    \item \texttt{open} nimmt ein Encoding-Argument, wie \texttt{codecs.open}
    \item Standardencoding nun UTF-8 statt ASCII
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Weiterführende Informationen}
  \begin{block}{Hauptquelle dieser Folien}
    Besten Dank an Kumar McMillan für \url{http://farmdev.com/talks/unicode/}.
  \end{block}
  \begin{block}{Wiki}
    \begin{itemize}
      \item \url{http://wiki.python.de/Von_Umlauten,_Unicode_und_Encodings}
      \item \url{http://wiki.python.de/Unicode}
    \end{itemize}
  \end{block}
  \begin{block}{Weitere Artikel}
    \begin{itemize}
      \item \url{http://www.joelonsoftware.com/articles/Unicode.html}
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}
  \frametitle{Das wars}
  \begin{block}{Was jetzt?}
    Fragen?
  \end{block}
\end{frame}

\end{document}
