デコレータの基本について理解したのでまとめる
Pythonのデコレータに関して、理解していることをまとめてみる。
@
を使ったデコレータの書き方はただのシンタックスシュガー
(読み書きのしやすさのために導入される構文)。
それでは、何に対するシンタックスシュガーなのか。
まず、以下のようなプログラムがあるとする。
def egg(): return "egg" if __name__ == '__main__': print(egg()) # egg
実行すると、当たり前だが以下の様な結果になる。
egg
次に、先ほどのファイルにscramble
というメソッドを追加する。
def scramble(egg): def _scramble(): return "scramble " + egg() + "!" return _scramble def egg(): return "egg" if __name__ == '__main__': scramble_egg = scramble(egg) print(scramble_egg()) # scramble egg!
scramble
メソッドは、オブジェクトを1つ受け取り、内部に定義されている_scramble
メソッドを返している。
つまり、scramble
メソッド自体は引数に対して何かを行うことはなく、
ただ内部のメソッドを返しているだけの機能しか持っていない。
返される内部メソッドの_scramble
は、scramble
メソッドが受け取ったの返り値に、
"scramble "と"!"という文字列を装飾(デコレート)して返している。
if __name__ == '__main__'
では、scramble
メソッドにegg
メソッド渡し、
返り値をscramble_egg
という変数に格納している。
scramble
メソッドの返り値は_scramble
のため、scramble_egg
変数は
_scramble
メソッドの内容と同じ挙動をする。
そのため、ファイルを実行すると以下の様な実行結果になる。
scramble egg!
さて、if __name__ == '__main__'
の中ではscramble
メソッドの返り値はscramble_egg
という変数に格納していた。
ここで、すでに定義されているegg
メソッドにscramble
の返り値を格納してみる。
Pythonはメソッドも変数も全てがオブジェクトのため、こういうことができる。
def scramble(egg): def _scramble(): return "scramble " + egg() + "!" return _scramble def egg(): return "egg" if __name__ == '__main__': egg = scramble(egg) # この部分と print(egg()) # この部分
実行結果は上記と同じscramble egg!
。
egg
に対してscramble
メソッドの返り値を格納しているため、egg
メソッドは
元の「"egg"という文字列を返す」という機能が上書きされている。
しかし、ただ上書きされたわけではなく、scramble
メソッドに元の機能を引数として渡しているため、
「"egg"という文字列を返す」機能は、_scramble
内で使われることになる。
この状態におけるscramble
メソッドがデコレータとなる。
文字通り別のメソッドを装飾することができる。
これまでの手順を@
を使って書き換えると、以下のようなコードになる。
def scramble(egg): def _scramble(): return "scramble " + egg() + "!" return _scramble @scramble def egg(): return "egg" if __name__ == '__main__': print(egg()) # scramble egg!
Webサーバをapacheからnginxに移行
今までapacheで動かしていたWebサーバをnginxにようやく切り替えた。 その中でしたnginxの設定とか詰まったところとかメモ。
nginxの設定
全体に関わる設定
http://www.nametake.info
のように、特に設定をしていないサブドメインに
アクセスがあっても、全部nametake.infoのページと同じ内容が表示されるようにしたい。
ということで、以下のようにdefault.conf
ファイルを書いて、デフォルトのバーチャルホストを設定する。
また、server_name
を_
にすることで、catch-allサーバとして設定。
default.conf
server { listen 80 default_server; server_name _; root /var/www/html; ~~~略~~~ }
あとは、nginxのバージョン番号とかOSの情報をレスポンスヘッダに含めたくないので、以下をnginx.conf
に追記。
nginx.conf
http { ~~~略~~~ server_tokens off; }
SSLに関わる設定
やりたかったこと
nametake.info
のサブドメインで動かしているownCloudとかampacheの通信経路を暗号化したい- 設定ファイルはサービスごとに分割したい
owncloud.conf
とかampache.conf
とかに証明書の情報をいちいち書きたくない
やったこと
以下のようにSSL全体の設定も記述(と言ってもほとんどexample_ssl.confのまんま)。 サーバ証明書と秘密鍵は、apacheを設定した時に作成したオレオレ証明書があるので、それをそのまま流用。
変更したのはlisten
の部分のdefault_server
と、server_name
の部分のバーチャルホスト。
ssl.conf
server { listen 443 ssl default_server; server_name .nametake.info; ssl_certificate /my/cert/file; ssl_certificate_key /my/cert/key/file; ~~~略~~~ }
上記のようにssl.conf
としてSSL全体の設定ファイルを作成することで、それぞれのサービスで
SSLを使用するときは、以下のように記述するだけでOK。
owncloud.conf
server { # 80番ポートでアクセスしてきたら443番ポートにリダイレクト listen 80; server_name cloud.nametake.info; # enforce https return 301 https://$server_name$request_uri; } server { listen 443 ssl; server_name cloud.nametake.info; ~~~略~~~ }
SSL通信したいサーバでlisten 443 ssl
と書くだけ。これで個別のファイルに証明書の情報を書かなくてよくなる。
サービスごとの細かいnginxの設定は[nginx (サービス名)]
とかで検索して出てきた結果をコピペ。
詰まったところ
ownCloudのログイン画面でリダイレクトループする
原因
/var/lib/php/session/
のパーミッションがapache:apache
のままになっていた。
解決策
/var/lib/php/session/
のパーミッションをnginx:nginx
に変更。
こんなところのパーミッションの設定もapacheになっていたのは想定外だった…… (serverのrootに指定したディレクトリの所有者がapacheのままになっていたのに気付かなくて30分ぐらい悩んだのは内緒)
.gitignoreの範囲の指定方法
過去に書いた記事をそのまま移行します。
前提
$HOME
ディレクトリ上でドットファイルをgitを管理している。
.gitignoreはホワイトリスト方式で記述している。
やりたかったこと
$HOME └── .vim ├── bundle ├── snippet ├── syntax ├── template └── userautoload
上記の構造になっているvimの設定ファイルのbundle
ディレクトリ以外をgitの管理下に置きたい。
(bundle
ディレクトリだけはgitで管理したくない)
やったこと
ホワイトリスト方式で.gitignore
を設定したが、階層構造をとっている時の設定でつまずいた。
ダメだったパターン
以下のように記述したら$HOME/.vim/
以下のディレクトリ内部のファイルが読み込まれなかった。
# all file ignore /* /.* # target not ignore !/.gitignore !/.vimrc !/.vim/template/template.* !/.vim/userautoload/*.vim !/.vim/snippet/*.vim !/.vim/syntax/*.vim
よく考えると、上の3行ですべてのファイルとディレクトリを場外しているため、
$HOME/.vim
ディレクトリがそもそもgitから見えない。
そのため、!/.vim/userautoload/*.vim
のようにファイルを指定しても、
!/存在しないディレクトリ/userautoload/*.vim
となっているので、
読み込まれることがなかった。
成功したパターン
以下のように記述したら成功した。
# all file ignore /* /.* # target not ignore !/.gitignore !/.vimrc # .vim directry !/.vim/ /.vim/* !/.vim/template/ !template.* !/.vim/syntax/ !*.vim !/.vim/snippet/ !*.vim !/.vim/userautoload/ !*.vim
やっていることは、
!/.vim/
で$HOME/.vim/
ディレクトリをホワイトリストに追加/.vim/*
で$HOME/.vim/
以下のファイルとディレクトリを除外!/.vim/userautoload/
で該当のディレクトリをホワイトリストに追加!*.vim
で*.vim
ファイルをホワイトリストに追加
という感じ。
ただ、一つのファイルで管理すると見栄えが悪かったので以下のように分割。
# $HOME/.gitignore # all file ignore /* /.* # target not ignore !/.gitignore !/.vimrc !/.vim/
# $HOME/.vim/.gitignore # all file ignore /* /.* !/.gitignore # target not ignore !/template/ !template.* !/syntax/ !*.vim !/snippet/ !*.vim !/userautoload/ !*.vim
これで管理しやすくなった。