<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>meier-online &#187; Python</title>
	<atom:link href="http://meier-online.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://meier-online.com</link>
	<description>Der Blog von Karsten Meier</description>
	<lastBuildDate>Sun, 09 Oct 2011 13:27:57 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Fremde Daten mit der AppEngine verarbeiten</title>
		<link>http://meier-online.com/2008/08/fremde-daten-mit-der-appengine-verarbeiten/</link>
		<comments>http://meier-online.com/2008/08/fremde-daten-mit-der-appengine-verarbeiten/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 15:36:00 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[AppEngine]]></category>
		<category><![CDATA[fetch]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SSL]]></category>

		<guid isPermaLink="false">http://meier-online.com/blog/?p=164</guid>
		<description><![CDATA[Die AppEngine erlaubt es auch, Webseiten oder andere Daten von fremden Servern abzurufen und zu verarbeiten. Das muss verständlicherweise beschränkt werden, da das Missbrauchspotential sehr hoch ist. Es können deshalb nicht beliebige Internetdienste aufgerufen werden, sondern nur &#8220;Webseiten&#8221; bzw. alles, was ein Webserver auf Port 80 oder 443 anbietet.Dazu dient das Modul urlfetch. Der einfachste [...]]]></description>
			<content:encoded><![CDATA[<p>Die AppEngine erlaubt es auch, Webseiten oder andere Daten von fremden Servern abzurufen und zu verarbeiten.<br />
Das muss verständlicherweise beschränkt werden, da das Missbrauchspotential sehr hoch ist. Es können deshalb nicht beliebige Internetdienste aufgerufen werden, sondern nur &#8220;Webseiten&#8221; bzw. alles, was ein Webserver auf Port 80 oder 443 anbietet.<span id="more-164"></span>Dazu dient das Modul urlfetch. Der einfachste Aufruf ist:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">api</span> <span style="color: #ff7700;font-weight:bold;">import</span> urlfetch
...
<span style="color: black;">response</span> = urlfetch.<span style="color: black;">fetch</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
content = response.<span style="color: black;">content</span></pre></div></div>

<p>Wenn alles gut geht, reicht das schon. So weit ist es sehr praktisch. In der Praxis muss man jede Menge Fehler abfangen, zum Beispiel wie in diesem Ausschnitt:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">    <span style="color: #ff7700;font-weight:bold;">try</span>:
        response = urlfetch.<span style="color: black;">fetch</span><span style="color: black;">&#40;</span>jadurl<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> response.<span style="color: black;">status_code</span> == <span style="color: #ff4500;">200</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">xxheaders</span> = response.<span style="color: black;">headers</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">xxcontent</span> = response.<span style="color: black;">content</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">xxFetched</span> = <span style="color: #008000;">True</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> response.<span style="color: black;">status_code</span> == <span style="color: #ff4500;">404</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">errortext</span> = <span style="color: #483d8b;">&quot;File not found&quot;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">xxcontent</span> = <span style="color: #483d8b;">&quot;not found&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">errortext</span> = <span style="color: #483d8b;">&quot;Bad Response Code&quot;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">xxcontent</span> = response.<span style="color: black;">status_code</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> InvalidURLError:
        <span style="color: #008000;">self</span>.<span style="color: black;">errortext</span> = <span style="color: #483d8b;">&quot;Invalid URL&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> DownloadError:
        <span style="color: #008000;">self</span>.<span style="color: black;">errortext</span> = <span style="color: #483d8b;">&quot;Error downloading file&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> ResponseTooLargeError:
        <span style="color: #008000;">self</span>.<span style="color: black;">errortext</span> = <span style="color: #483d8b;">&quot;File to large&quot;</span></pre></div></div>

<p>Man hat auch Zugriff auf die HTTP-Header, beispielweise erhält man den Mime-Type mit</p>
<p><span style="font-family:courier new;">response.headers</span>[<span style="font-family:courier new;">'content-type']<br />
</span></p>
<p>In meinen speziellen Fall würde mich auch interessieren, ob ein Header doppelt geschickt wird. Diese Information scheint man leider nicht zu bekommen.</p>
<p>Man kann auch SSL-geschützte Seiten mittels &#8220;https://&#8221; runterladen. Leider werden dabei derzeit (1.1.) laut Dokumentation die Zertifikate nicht geprüft, sprich die stärkere Sicherheit ist nicht da. Das schränkt die Anwendung zurzeit noch ein.</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2008/08/fremde-daten-mit-der-appengine-verarbeiten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dateiupload mit der AppEngine</title>
		<link>http://meier-online.com/2008/07/dateiupload-mit-der-appengine/</link>
		<comments>http://meier-online.com/2008/07/dateiupload-mit-der-appengine/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 15:26:00 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[AppEngine]]></category>
		<category><![CDATA[Dateiupload]]></category>
		<category><![CDATA[file upload]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://meier-online.com/blog/?p=166</guid>
		<description><![CDATA[In CGI-Programmen muss man, wenn man einen Dateiupload anbieten möchte, oft mit temporären Dateien jonglieren. Nun hat man in dieser verteilten Umgebung gar kein Schreibzugriff auf ein Dateisystem im klassischen Sinne. Zunächst habe ich eine Weile in der Dokumentation gesucht, um zu finden, wie es mit der AppEngine geht. Erst in einem Beispiel zur Bildbearbeitung [...]]]></description>
			<content:encoded><![CDATA[<p>In CGI-Programmen muss man, wenn man einen Dateiupload anbieten möchte, oft mit temporären Dateien jonglieren. Nun hat man in dieser verteilten Umgebung gar kein Schreibzugriff auf ein Dateisystem im klassischen Sinne. Zunächst habe ich eine Weile in der Dokumentation gesucht, um zu finden, wie es mit der AppEngine geht. Erst in einem Beispiel zur Bildbearbeitung bin ich dann fündig geworden.<span id="more-166"></span><br />
Es ist schlicht zu einfach. Hat man ein HTML-Eingabefeld zum Upload mit Namen &#8220;uploadfile&#8221;, dann greift man auf die hochgeladenen Daten einfach so zu:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">filecontent = <span style="color: #008000;">self</span>.<span style="color: black;">request</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'uploadfile'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Der Dateiinhalt befindet sich danach in der Variable &#8220;filecontent&#8221;. Wenn es eine Textdatei ist, kann ich den Inhalt einfach wie einen String verarbeiten.<br />
Für viele Anwendungsfälle ist das sehr bequem und ist völlig ausreichend. Interessant wäre noch zu wissen:</p>
<ul>
<li>Wie kommt man an den ursprünglichen Dateinamen ran?</li>
<li>Kann man möglichst früh die Verarbeitung verweigern, wenn die Datei zu groß ist?</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2008/07/dateiupload-mit-der-appengine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>App Engine</title>
		<link>http://meier-online.com/2008/07/app-engine/</link>
		<comments>http://meier-online.com/2008/07/app-engine/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 17:48:00 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[AppEngine]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[webapp]]></category>

		<guid isPermaLink="false">http://meier-online.com/blog/?p=9</guid>
		<description><![CDATA[My first impressions and some notes about programming for Googles App Engine.]]></description>
			<content:encoded><![CDATA[<p>Google erlaubt, Webanwendungen auf ihren Servern laufen zu lassen. Ich habe mir das Angebot etwas näher angeschaut. Es folgen die ersten Notizen:<br />
Pflicht ist die Programmiersprache Python. Es gibt ein SDK, um seine Anwendungen zunächst auf den eigenen Rechner auszuprobieren sowie ein Tutorial.<br />
Ich habe mir das SDK in der Version 1.1 installiert und bin das Tutorial durchgegangen.<span id="more-9"></span></p>
<p>Das SDK kommt mit einem eigenen Webserver. Man startet den Servers mit<br />
<span style="font-family:courier new;">dev_appserver.py helloworld</span><br />
Im Verzeichnis muß eine Konfigurationsdatei im Yaml-Format liegen. In dieser Datei werden URLs den Python-Dateien oder auch Bildern, etc zugeordnet. Fehlt die Datei, oder enthält sie nicht die benötigten Informationen, wird eine Exception geworfen.</p>
<p>Einige Dateien werden werden automatisch in Starverzeichnis des Nutzers angelegt, man kann diese leicht mal übersehen:<br />
eine Konfigurationsdatei des SDK in userdir/.appcfg_nag sowie ein Datastore (praktisch die Datenbank) in userdir\temp\dev_appserver.datastore</p>
<p>Enthalten ist ein kleines Framework mit Namen &#8220;WebApp&#8221;.</p>
<p>Um den Python-Code vom HTML-Code zu trennen, gibt es eine Template-engine mit Django-kompatibler Syntax.<br />
Ich hatte ein Problem mit den Templates: der <em>XML-Header()</em> am Anfang führte dazu, dass diese nicht angezeigt wurden.</p>
<p>Die Template-Sprache selbst nutzt geschweifte Klammern. Das ist verhältnismäßig kompakt, leider kann dadurch das Template schnell zu invaliden HTML-Code ausarten, so dass man das Template selber kaum noch im Browser überprüfen kann.</p>
<p>Zum Speichern der Daten einer Webanwendung nutzt man weder die sonst allgegenwärtigen SQL-Datenbanken noch das Dateisystem. Statt dessen gibt es ein spezielles Storage. Positiv dabei: Man kann eine Klasse einfach von &#8220;<em>db.Model</em>&#8221; ableiten, und die Objekte lassen sich dann komplett in den Datastore schreiben und lesen. Um die einzelnen Instanzvariablen muss man sich keine Gedanken machen, und man muss auch keine Datenbanktabellen deklarieren. Eine SQL-ähnliche Abfragesprache gibt es auch, aber offenbar eher als &#8220;syntaktischer Zucker&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2008/07/app-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

