タワ記

気が向いた時にだけ書く、技術メモっぽいもの。

VMware Fusion + Ubuntu 16.04で日本語入力の切り替えを設定する

※この記事はUbuntu 16.04を前提として記載しています。

この記事に書いてあること

  • [かな]キーでMozcをONにするよ。
  • [英数]キーでMozcをOFFにするよ。

発端

iMac + Apple Wireless Keyboard (JIS)という環境なのですが、初期設定のままだとVMware Fusion上のUbuntuで日本語入力できなくて普通に困ります。

仮装マシン設定

[キーボードとマウス]は、「プロファイル-デフォルト」を選んでおきます。
その他は特にいじっていません。

インストール時

キーボードの設定は「日本語」を選びます。「日本語 - Macintosh」は選びません。

Ubuntu設定

  • 通知アイコンにあるキーボードのアイコンを右クリック→[設定]
  • [入力メソッド]タブでMozcを選ぶ
  • [全体の設定]タブを開く
  • [全体の設定]タブ内の[ホットキー]タブを開く(デフォルトで開いているはず)
  • [入力メソッドのオンオフ]を両方ともHiraganakatakana(かなキー)にする(雑!)
  • [ホットキー]タブ下部にある[拡張オプションの表示]にチェックを入れる
  • [入力メソッドをオンに]にHiraganakatakana(かなキー)を設定する
  • [入力メソッドをオフに]にEisutoggle(英数キー)を設定する

以上でmacOS同様に、かなキーで日本語入力、英数キーで英数入力に切り替えられます。

FlaskでHTMLなHello World!

※この記事はUbuntu 16.04、Python3.5、Flask 0.12.2を前提として記載しています。

この記事に書いてあること

  • 戻り値にHTMLを入れてやればいいよ。
  • テンプレートエンジンを使えばHTMLをPythonコードから簡単に分離できるよ。
  • 単に分離するだけでなく、Pythonコードからテンプレートにパラメータを渡して、生成されるHTMLの内容を変えてみるよ。

HTMLを返してみる

公式Hello World!は以下のようなコードでした。

hello.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

"/"にアクセスしたらHello World!という文字列がそのまま返っていました。ということは、ここにそのままHTMLを書いてやれば、HTML版Hello World!ができそうな気がします。

hello_html.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<html><body><h1>Hello World!</h1></body></html>"

Webブラウザで見てみると、こうなります。

f:id:twkmn:20171205222757p:plain
HTMLなHello World!

当然の結果になりました。

テンプレートエンジンを使う

とはいえ、毎度HTMLをWebアプリケーションのソースコードに埋めるわけにもいきません。
FlaskはJinja*1 2というテンプレートエンジンが統合されています。あらかじめHTMLのテンプレートを別ファイルとして用意しておき、Flaskから呼び出して利用することができます。

テンプレートはhello.pyと同じレベルにtemplatesというディレクトリを作り*2、そこに放り込んでおきます。

templates/base.html

<!DOCTYPE html>
<html lang="jp">
<head>
    <title>{{ title }}</title>
    <!--[if lt IE 9]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
</head>
<body>
    {% block content %}
    {% endblock %}
</body>
</html>

templates/hello.html

{% extends "base.html" %}
{% block content %}
<h1>{{ message }}</h1>
{% endblock %}

hello_template.py

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/')
def hello():
    return render_template("hello.html", title="Flask Page", message="Hello World!")

動かして、Webブラウザで結果を見てみましょう。

f:id:twkmn:20171205230513p:plain
TemplateでHTMLなHello World!

できたページのソースコードを表示すると、以下のようになります。

<!DOCTYPE html>
<html lang="jp">
<head>
    <title>Flask Page</title>
    <!--[if lt IE 9]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
</head>
<body>
        
<h1>Hello World!</h1>

</body>
</html>

Python上で設定したパラメータが反映されて、ちょっとWebアプリケーションっぽい雰囲気が出てきました。

*1:「神社」らしいのだけど、なぜ神社・・・

*2:暗黙的にtemplatesの中を探しに行きます

FlaskでHello World!

※この記事はUbuntu 16.04、Python3.5、Flask 0.12.2を前提として記載しています。

この記事に書いてあること

Flaskとは

Pythonで書けるWebアプリケーションフレームワークです。

私は元々組み込み系と呼ばれる分野を中心に仕事をしてきましたので、Web関係は縁遠い存在でした。しかし、仕事の幅が広がっていく上で「ちょっとしたWebアプリケーション」があればいいな、と思うことも増えてきました。

いまどきのWebアプリケーション開発といえば、フレームワークを使うんでしょ?くらいの知識はありましたが、いろいろあって何を使えばいいのか、すぐには分かりませんでした。とりあえずPythonなら慣れていて取っ付き易いかも・・という理由でPythonベースのFlaskを調べることにしました。

公式Hello World!

Welcome | Flask (A Python Microframework)を見ると、"Flask is Fun"ということで、いきなりHello Worldのコードらしきコードが出てきます。

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

なるほど、これは楽しいです。"/"にアクセスしたらHello World!が返りそうだ、ということが直感的に分かります。
この時点で私はFlaskを使って行こうと心に決めました。

でもWebアプリケーションって、Apacheなりnginxなりを設定して、Webサーバー立ち上げないといけなくて面倒だな・・・と思っていたのです。
しかし、上記公式ページのHello Worldの下には"And Easy to Setup"というのがあり、これを見ると単独でWebサーバーにもなってくれそうで、簡単そうじゃないですか!
せっかくPython3で仮想環境(venv)を使おう。 - タワ記も書いたので、venvを使った仮想環境も作りつつ試してみましょう。

$ python3 -m venv flask_hello
$ cd flask_hello
$ source bin/activate
$ pip install Flask

ここまでやって、あとは上記Hello Worldをhello.pyとして作成します。

$ FLASK_APP=hello.py flask run
 * Running on http://localhost:5000/

別のターミナルから、curllocalhost:5000/を読んでみます。

$ curl http://localhost:5000
Hello World!

素晴らしい。
ただし、これですと単に生テキストが返ってきているだけですので、次回はこれを少し発展させて、htmlなHello Worldを返してみることにします。

Python3で仮想環境(venv)を使おう。

※この記事はUbuntu 16.04、Python3.5を前提として記載しています。

この記事に書いてあること

  • venvを使って開発するアプリケーションに応じて、実行環境を閉じよう。
  • $ python3 -m venv fooで仮想環境を作るよ。
  • $ cd fooして$ source bin/activeで閉じた環境に入るよ。
  • $ deactivateで戻るよ。
  • ググるPythonの仮想環境について色々と出てくるのだけど、いまいま(2017.12)の時点ではこれが標準っぽいよ。

Pythonが好きだけど

普段は仕事柄、C++(あるいはC)を使うことが多いのですが、スクリプト言語ではPythonが好きです。

理由は・・・なんでしょうね。フィーリングでしょうか。あくまでも一個人の感想に過ぎませんが、とにかく何かちょっとしたものを作る時に、余計なことを考えずに作れる気がします。

ライブラリも充実していて、なおかつ大概のライブラリはpipという標準の*1パッケージマネージャを使って、簡単に組み込むことができます。たとえばgevent*2というネットワーキングライブラリを使いたくなったら、

$ sudo pip3 install gevent 

のようにしてインストールすることが可能です。

しかしこの方法ですと、システム全体*3に影響を与えます。具体的には、/usr/local/lib/python3.5/dist-packages/というディレクトリにインストールされます。

お一人様で開発をしている分にはあまり問題にならない*4のですが、例えばサーバー上でアプリケーションfooとbarを動かす場合、foo、bar共通で利用するライブラリのバージョンアップをしたら、fooは動くけどbarは動かなくなった!ということが起こらなくもないです。

仮想環境とは

そこで仮想環境を使おう、ということになります。仮想環境というと何やら難しげですが、ここで述べる仮想環境は「一つのシステム上にありながら、アプリケーションごとに別々のPython実行環境があるように見せかける」という捉え方でよいかと思います。

インストール

$ sudo apt install python3-venv 

使い方

アプリケーションfoo用の仮想環境を用意します。

$ python3 -m venv foo

カレントディレクトリ下にfooディレクトリが作成されるので、カレントディレクトリをfooに移します。

$ cd foo

仮想環境に入ります。

$ source bin/activate

これでfoo用の仮想環境に入りました。プロンプトの先頭に(foo)が付いて、foo用の仮想環境にいることを示してくれます。仮想環境から抜ける時は、

$ deactivate

で抜け出せます。

試す

仮想環境に入った状態でpipを使ってライブラリをインストールすれば、その仮想環境上にだけインストールすることが可能です。

$ cd foo
$ source bin/activate
$ pip3 install gevent

これでfooの仮想環境にのみgeventライブラリがインストールされるはずです。
試しに以下のような適当なコード(foo.py)を書きます。

import gevent
print("Hello")

geventをimportしているだけで特に意味はありません。

$ python3 foo.py
Hello

インストールされたgeventがきちんと解決できているので、エラーになりません。仮想環境から抜け出した場合はどうでしょうか。

$ deactivate
$ python3 foo.py
Traceback (most recent call last):
File "test.py", line 1, in <module>
import gevent
ImportError: No module named 'gevent'

geventが仮想環境にしかインストールされていないので、エラーになりました。
このように、実行環境をアプリケーションごとに閉じることが可能です。
なお、仮想環境に入っている状態でpipを使いインストールされたライブラリは、foo/lib/python3.5/site-packagesに入ります。例えば適当にライブラリを組み合わせて作ったツールなどを他の人に渡す場合、fooディレクトリを固めて渡せば、実行時にactivateを実行してもらうだけで済むので、いちいち「このライブラリとこのライブラリをインストールして・・・」みたいなことを伝えずに済むというメリットもあります。
というわけで、積極的に仮想環境を使いましょう。

ちなみにPythonで仮想環境を利用する方法は、調べるといくつか出てくるのですが、この記事を書いている時点ではこれが標準のようです。Python2については他の方法を使うようですが、ここでは省略します。

*1:Python 3.4以降の場合

*2:What is gevent? — gevent 1.3.0.dev0 documentation

*3:というと少々大袈裟ですが。

*4:なる場合もあるよ!