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アプリケーションの起動方法の有効性の比較

Source: https://habr.com/ru/post/J256481/


All Articles