PythonスクリプトからWSGIアプリケーションへ

デバイス管理Webインターフェースを作成するタスクがありました。 デバイスはRaspberry Piによって制御されます。 制御ロジックはそれぞれpythonであり、インターフェースはpythonが必要です。 私の経験を共有したいです。







1.「額に」問題を解決するために、mod_cgiでlighttpdが発生しました。



sudo apt-get install lighttpd sudo nano /etc/lighttpd/lighttpd.conf
      
      





lighttpd.confの抜粋:



 #mod_cgi shoud be on server.modules = ( "mod_access", "mod_alias", "mod_compress", "mod_redirect", "mod_cgi", "mod_rewrite", ) #rule enables cgi script cgi.assign = (".py" => "/usr/bin/python")
      
      





/var/www/index.py:



 print "Content-Type: text/html\n\n" print "Hello World!"
      
      





localhost / index.pyが元気いっぱいの 「Hello World!」



lighttpdが拡張子.pyのファイルに遭遇すると、実行のためにそのファイルをpythonに渡し、その結果がリクエストに応答します。 大まかに言えば、stdoutをリダイレクトします。

インターフェイスを「ゼロから」作成しようとすると、 HtmlGeneratorが誕生しました。これにより、HTMLタグでコードをオーバーロードできなくなり、非常にシンプルになりましたが、それでも複雑な問題は解決しませんでした。



2. Webフレームワークを試すことが決定されました。

シンプルで軽量Wep.pyが手に入りました。

code.py:



 #! /usr/bin/python # import web urls = ( '/', 'index',) class index: def GET(self): return "Hello, world!" if __name__ == "__main__": web.application(urls, globals()).run()
      
      





最小限のコードとポート8080でWebアプリケーションがハングします

エイリアスをポート8080に転送し、スクリプトの自動起動を整理すると、完了です。

はい、しかしそうではありません。弱いコンピューターでの実験では、スクリプトの存在がマシンをかなり「不機嫌」にしていることが示されました。 さらに、mod_cgiでlighttpdがあります。



簡単なスクリプトとWebアプリケーションを接続する方法。



3. WSGIの説明によると、その実装にはこの種のインターフェースが必要です。

 #! /usr/bin/python # def myapp(environ, start_response): status = '200 OK' response_headers = [('Content-type','text/plain')] start_response(status, response_headers) return ['Hello World!\n']
      
      





軍事的なものはありませんが、何かが機能せず、何かが欠けています。

ウィキや他の記事を読んだ後は不明瞭でしたが、すべて同じようにインターフェースが起動します。



4. WSGIアプリケーションを開始するには、サーバーが必要です。 単純なWSGIサーバーとして機能できるサンプルスクリプト:

wsgi.py:

 #! /usr/bin/python import os import sys def run_with_cgi(application): environ = dict(os.environ.items()) environ['wsgi.input'] = sys.stdin environ['wsgi.errors'] = sys.stderr environ['wsgi.version'] = (1, 0) environ['wsgi.multithread'] = False environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] = True if environ.get('HTTPS', 'off') in ('on', '1'): environ['wsgi.url_scheme'] = 'https' else: environ['wsgi.url_scheme'] = 'http' headers_set = [] headers_sent = [] def write(data): if not headers_set: raise AssertionError("write() before start_response()") elif not headers_sent: status, response_headers = headers_sent[:] = headers_set sys.stdout.write('Status: %s\r\n' % status) for header in response_headers: sys.stdout.write('%s: %s\r\n' % header) sys.stdout.write('\r\n') sys.stdout.write(data) sys.stdout.flush() def start_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: raise exc_info[0], exc_info[1], exc_info[2] finally: exc_info = None elif headers_set: raise AssertionError("Headers already set!") headers_set[:] = [status, response_headers] return write result = application(environ, start_response) try: for data in result: if data: write(data) if not headers_sent: write('') finally: if hasattr(result, 'close'): result.close()
      
      





インターフェイスに起動を追加すると、lighttpdまたはapacheのlocalhost / app.pyで既に応答するスクリプトが取得されます。

/var/www/app.py:

 #! /usr/bin/python include wsgi def myapp(environ, start_response): status = '200 OK' response_headers = [('Content-type','text/plain')] start_response(status, response_headers) return ['Hello World!\n'] if __name__ == '__main__': wsgi.run_with_cgi(myapp)
      
      







5. Python 2.7の場合、WSGIサーバーを実装できるwsgirefモジュールが利用可能です

 #! /usr/bin/python import wsgiref.handlers def myapp(environ, start_response): status = '200 OK' response_headers = [('Content-type','text/plain')] start_response(status, response_headers) return ['Hello World!\n'] if __name__ == '__main__': wsgiref.handlers.CGIHandler().run(myapp)
      
      







6. flupを使用したWSGIの実装:

flupをインストールする

 sudo apt-get install python-flup
      
      





 #! /usr/bin/python import flup.server.fcgi def myapp(environ, start_response): status = '200 OK' response_headers = [('Content-type','text/plain')] start_response(status, response_headers) return ['Hello World!\n'] if __name__ == '__main__': flup.server.fcgi.WSGIServer(myapp).run()
      
      







7. flupを使用した単純なweb.pyアプリケーション:

/var/www/app.py:

 #! /usr/bin/python import web urls = ( '/', 'index', ) class index: def GET(self): return "Hello World!" if __name__ == '__main__': web.application(urls, globals()).run()
      
      





アプリケーションはlocalhost / app.pyで利用可能になります



8.デフォルトでは、web.pyはflupを使用しますが、flupなしでも実行できます。

wsgirefでweb.pyを実行するには、以下を行う必要があります。

 web.application(urls, globals()).cgirun()
      
      





web.pyスクリプトへのリンクでは、末尾に「/」(app.py/)を忘れないでください。そうしないと、答えが「見つかりません」になります。 良い方法では、書き換えルールを作成する必要があります。

 # mod_rewrite configuration. url.rewrite-once = ( "^/favicon.ico$" => "/favicon.ico", "^/(.*)$" => "app.py/$1" ,)
      
      





スクリプトでデバッグするには、次を追加すると便利です。

 import cgitb cgitb.enable()
      
      





エラーが表示されます。



試してみてください:

modwsgi

貼り付ける

パイロン



便利なリンク:

WSGI wiki

wep.py

WSGI-Pythonアプリケーションを使用したWebサーバー通信プロトコル

WSGIの紹介

CGIを介してWSGIアプリケーションを提供する方法

WSGI.org

Python Webアプリケーションの起動方法の有効性の比較



All Articles