はじめに
1回で終わるのかシリーズ化するのか、今日はどこまで進むのかとにかく行き当たりばったりですが、「やってみた」を記録するものです。
さくらインターネットのレンタルサーバー最安プランを借りて
Pythonで開発したWebアプリを動かしてみます。
この通りやればこの通りの結果は得られるでしょうが、何かを少しでも変更した場合にどうなるかについては基本的には言及しません。
つまりは、やっぱり「やってみた」を記録するものです。
目次
さくらのレンタルサーバ
このシリーズで扱う内容はおそらくどこのレンタルサーバーでも通用すると思いますが、さくらのレンタルサーバーの最安プランであるライトでは、Pythonを動かす方法はsshによるログインが出来ない状態でのcgiのみです。もしスタンダード以上のプランをお選びの場合”さくら django”あたりでググるともう少し高級なことが出来ると思います。
さて、このシリーズにお付き合いくださってさくらのレンタルサーバーのご契約されるのであれば、以下を踏んでいただけると幸いです。高いプランにご契約いただければ頂けるほどありがたいのですが、ここでの記事の内容は最安のライトプラン(月換算131円)です。
何度となくさくらのレンタルサーバー、さくらのVPSなどを利用しておりますが、可もなく不可もないというのが私の評価です。表現/字面上はイマイチですが、この世界で生活の糧を得ている者としては、なかなか実現が難しいことを身に染みて分かっております。他の人におすすめするかと問われればおすすめします。品質はどうか?と聞かれれば、良いサービスですと答えます。自分は何を使っているのかと問われれば違うサービスを使っているのですが、、、
何が課題なのか
多くのレンタルサーバーの最安プランも同じかと思いますが、PHPとMySQLで動的ページを構成するというのが主眼にあり、他のスクリプト言語は形式上使えますよと言うために用意されている程度かと思います。
Pythonで動的ページ(DBや他のサービスにアクセスしてその結果に応じて表示するコンテンツが変わるページ)を望んだ場合、当サイトでも紹介しているDjango、それにFlaskなどに代表されるフレームワークを用い、それ自体がサーバーとして稼働するものを準備します。いわゆるApacheやNginxなどのWebサーバーはそのフロントに立って前捌きを行っているだけです。
ところが、さくらのレンタルサーバーのライトプラン(最安プラン)では、sshによるログインも出来ないですし、PythonプログラムをCGIとして動かさなければなりません。おまけにVersionも2.7系ということで絶滅危惧種です。最後の2.7系である事実は受け入れる以外ありませんが、なんとかCGIでも本格的な構成で実装したいというのが今回の目的です。
今回何を使うのか
今回は1ファイルでフレームワーク機能を提供するBottleというフレームワークを使用します。
Bottle: Python Web Framework — Bottle 0.12.19 documentation (bottlepy.org)
現時点で0.12.19というのが最新バージョンですが、Gitのリポジトリ上は9 Oct 2016の0.12.10から始まり、 12 Nov 2020の最新ということで、コツコツと今も開発が続いています。
1ファイルで全機能を提供してくれるということは、実環境に配置するのが恐ろしく簡単というメリットがありますね。最安プランではDBが提供されていないので、SQLiteをDBを使うことにしますが、SQLiteへの接続は標準で用意されているため、
- index.cgi ・・・プログラム本体
- bottle.py ・・・フレームワーク本体
- sqlite.db ・・・DBファイル
という3ファイルあると実現可能ということになります。
まずはCGIを動かす
まずは以下の様に簡単な1行を返却するCGIを作ってみます。
Hello World!
ソースコードは以下の通りです。気をつけないといけないのは、ファイル名の拡張子はcgiです。これはさくらのレンタルサーバーで決められていることなので従う必要があります。
hello.cgi
#!/usr/local/bin/python # coding=utf-8 print("Hello World!")
1行目はさくらのレンタルサーバーのコンソールに「各種コマンドのパス」という画面があり、そこで確認することが出来ます。
そして、4行目のprint文が本題の”Hello World!”を出力している行です。
それらをUTF-8で保存しなければなりません。間違えてもBOM付きにしないように気をつけてください。それをファイルマネージャーかFTPクライアントを使ってホームディレクトリのwwwディレクトリ以下にコピーします。
その上、ファイルのパーミッションは755となっている必要があるので、ファイルを選択の上で”操作”をクリックしプロパティを表示して”値で指定”の欄に755を入力して”OK”をクリックします。
これで準備はOKのはずです。ブラウザから初期ドメイン+/hello.cgiへアクセスしてみてください。
Bottleにチャレンジ
まずはお手元の環境(PC環境)が、Pythonのバージョンが2.7系であることを確認してください。個人的にはpyenvを使用してPythonのバージョンは切り替えているので、もしその方向でお考えでしたら以下を参考にしてください。
Bottleのインストール
といってもファイルをコピーするだけなのですが、例えば以下のコマンドで手に入れます。
wget http://bottlepy.org/bottle.py
もちろんpipコマンドでインストールしてもいいのですが、最終的にはCGIとしてファイルをコピーするということは、手で集める必要があるので、どうせなら最初から目に見えるところにという考え方です。
main.cgi
#!/usr/local/bin/python # coding=utf-8 from bottle import route, run # # web # @route('/hello') def hello(): return "Hello World!" run(host='localhost', port=8080, reloader=True, debug=True)
このソースコード自体は、Bottleの公式にあるQUICKSTARTを基本そのままに使っています。
Bottleの使い方自体は別途記事にしたいと思いますが、見てお分かりの通り、/helloにアクセスするとhello()が実行され、つまりは”Hello World!”が返却されるということになります。
ついでにrun()の引数で、localhostをホスト名に、8080をポート番号に、デバッグモードをOnにするという指定をしています。オリジナルと違うところはここだけで、開発中のソースコード変更時に自動的に立ち上げ直ししてくれるreloaderを指定してます。これを指定しないと、変更のたびにサーバーを立ち上げ直す必要が生じます。
そして最終的にはこのrunの引数指定でCGIに切り替えます。
実行
MacBookPro:bottle $ python -V Python 2.7.18 MacBookPro:bottle $ python main.cgi Bottle v0.12.19 server starting up (using WSGIRefServer())... Listening on http://localhost:8080/ Hit Ctrl-C to quit.
はい、サーバーが立ち上がるので、この時点では何も起こりません。ブラウザでhttp://localhost:8080/helloにアクセスすると結果が得られます。
ブラウザ
コンソール(ログ)
MacBookPro:bottle $ python main.cgi Bottle v0.12.19 server starting up (using WSGIRefServer())... Listening on http://localhost:8080/ Hit Ctrl-C to quit. Bottle v0.12.19 server starting up (using WSGIRefServer())... Listening on http://localhost:8080/ Hit Ctrl-C to quit. 127.0.0.1 - - [15/Aug/2021 15:59:42] "GET /hello HTTP/1.1" 200 12
Bottleをさくらのレンタルサーバーで動かしてみる
さていよいよレンタルサーバー上で動かしてみます。Bottleのマニュアルの最後の方にdeploymentの節にリンクがある別ドキュメントに詳細が書いてありますが、CGIでの動作もサポートしています。これを利用することでBottleの恩恵に預かりながらCGIで動かします。
やり方は実に簡単で、身も蓋もありませんが、以下の様に指定します。
bottle.run(server='cgi')
main.cgi
#!/usr/local/bin/python # coding=utf-8 from bottle import route, run @route('/hello') def hello(): return "Hello World!" # run(host='localhost', port=8080, reloader=True, debug=True) run(server="cgi")
最後の行でcgi対応にしただけです。これとbottle.pyを先ほどと同じ手順でサーバーに配置し、ブラウザでアクセスしてみて下さい。ここで、/helloへアクセスするには、main.cgiに続けることでアクセス可能です。
SQLiteで動的ページ
さていよいよ最後のトピックです。これが出来れば、ベースになる部分は手に入ったも同然ですね。早速やってみます。
DBの作成
SQLiteのDBは単一のファイルとして作成されます。そのためテーブルと初期データを入れるところまでを役割としたスクリプトを1つ作成します。
init_db.py
# coding=utf-8 import sqlite3 dbname = 'main.db' # DBに接続する(未作成の場合、作成される) conn = sqlite3.connect(dbname) cur = conn.cursor() # テーブルの作成 cur.execute( 'CREATE TABLE items(id INTEGER, name TEXT, price INTEGER)' ) # データ登録 cur.execute('INSERT INTO items values(0, "りんご", 100)') conn.commit() conn.close()
ID、名前、値段の3カラムのitemsテーブルを作成し、リンゴ100円を登録しています。おまじないが1行ありませんが、ローカルでしか動作させないので合ってもなくてもOKです。これを1度だけ実行します。実行しても成功した場合にはmain.dbファイルが出来る以外、標準出力に何も表示されないので実行結果の掲載は割愛します。
続いてこれを使ったページを作成します。
main.cgi
#!/usr/local/bin/python # coding=utf-8 import sqlite3 from bottle import route, run # # init # dbname = 'main.db' conn = sqlite3.connect(dbname) cur = conn.cursor() # # function # def select_db(): # データ検索 cur.execute('SELECT * FROM items') name = None # 取得したデータはカーソルの中に入る for row in cur: name = row[1] return name # # web # @route('/hello') def hello(): select() return "Hello World!" @route('/select') def select(): name = select_db() return name # # server # # run(host='localhost', port=8080, reloader=True, debug=True) run(server="cgi") # # end # conn.close()
色々と手抜きなのは大目に見て下さい。”/select”を新設しました。select_db()で先ほど1件登録した”りんご”を返却してくるはずなので、画面にも”りんご”と表示されたら成功です。
早速main.cgiとmain.dbをアップロードして試して見ます。SQLiteを操作するライブラリは標準で用意されているため、Bottleのように別途インストールしたりファイルをftpで転送したりする必要もありません。
無事に結果が得られましたでしょうか。
まとめ
さくらのレンタルサーバーのライトプランで、Bottleフレームワークを使って、DBにアクセスしてその結果を使って画面に表示することが出来ました。
まずは第一関門クリアといった所でしょうか。
このほか、cookieを使ったり、ヘッダを操作したり、GETリクエストのクエリ文字列を取得したりと、いわゆる普通のWebフレームワークが提供してくれている機能もCGIに切り替えても動作します。そのあたりはまた機会を改めてご紹介したいと思います。