おまじない

はじめてプログラムを目にすると「おまじない」の類いを目にすることがあると思います。ここでは以下の3つのおまじないについて説明します。

我らは魔法使いのはず。おまじないと呼ぶのはここで最後にしましょう。

ここで学習すること

  • shebang
  • __name__
  • # -*- coding: utf-8 -*-

サンプルコード

sample.py

#!/usr/bin/env python3.8
# -*- coding: utf-8 -*-

import sys

if __name__ == '__main__':
	argv = sys.argv
	print(argv)

説明

shebang

#!/usr/bin/env python3.8

まず1つめのおまじないはシェバンです。カタカタでの表記、読み方にはいくつかあるかと思いますが、ここではそういった話題は割愛します。

そして本来的にはPythonとは何の関係もありません。Unixの世界の話です。

Pythonを含むスクリプト言語で書かれたソースコードには、それ自体に動作する能力はありません。必ずOS上のソフトウェアが、スクリプト言語で書かれたテキストファイルを読み、そこに記載されているとおりに動くという構図になっています。したがって作成したソースコードを実行するときに、どのプログラムに引き渡せば良いのかを示す目印が必要で、それがシェバンと呼ばれるものです。

もっというとUnixではファイルを実行する時には、バイナリで出来ているソフトウェアであっても、まずファイルの先頭を見てから動作しています。先頭を見た結果テキストファイルであると判定されるとファイルの先頭を読み、#!で始まっている時にはその行に書かれているプログラムにそのファイル自身を引き渡すという流れで動作しています。

従ってUnixと同じ動作をしない環境では、この行は何の役にも立っていません。その上次のようにpythonを実行した場合には誰もこの文を気にしていません。

$ python sample.py

ではなぜ当サイトの例にこの行を書いているかというと、それは読む人にPython 3.8向けですよという目印になるためです。もちろん、Linux等で実行可能ファイルに指定した場合にそのまま動くことも期待のうちには含まれますが。

ついでなので、/usr/bin/envと書いている点についても触れておきます。以下のように書かれていることも有ると思います。

#!/usr/bin/python

もちろんこれでも動作すると思います。上記の書き方は、pythonコマンドを”このファイル”という形で指名している状態です。ここで残念なことは、pythonがバージョン2.xだった場合です。もし2つのバージョンのpythonがインストールされていた場合、/usr/bin/pythonはそのどちらかを指していて、それが2.7であった場合、3.8のpythonを呼び出すには/usr/bin/python3.8などとすることがあります。もう少し不幸な事態としては、python3.8は/usr/loca/bin/pythonにインストールされていて、/usr/bin/には存在しないというケースです。

/usr/bin/envにpython3.8を教えてもらうという形を取ることで、どこに入っているかは分からないが、あなたの環境のpython3.8コマンドで実行してくださいという1行になっています。

ですが、このトリック自体も普遍的に有効な訳ではないので、私は実際のプロジェクトでは使っていません。当サイトでは、意味を分かって人間が見てくれれば、3.8のPythonで実行して欲しいのだなと分かる目印として使っているという風にご理解ください。

__name__

続いてのおまじないは、__name__です。__と2回重ねているのは、裏方仕事を担っているおまじない系のもので、全くもって今すぐ理解する必要はない可能性は大いにありますが、百聞は一見にしかずです。以下を実行してみましょう。

sample01.py

#!/usr/bin/env python3.8

print(__name__)

実行結果

$ python sample01.py 
__main__
$ 

__main__と出ました。ちょうどサンプルコードでif 文の判定に使われている文字列です。

では、次の場合はどうでしょう。

sample2.py

#!/usr/bin/env python3.8

import sample01

print(__name__)

実行結果

$ python sample02.py 
sample01
__main__
$ 

ちょっと様子が変です。sample01.pyの__name__はsample01となり、sample02.pyの__name__は__main__となっているのです。実はsample01.pyをsample02.pyから利用しようとしてimportすると中身がいきなり実行されてしまいます。もちろん実行可能な行が無い場合には実行されません。__name__とは自分が一体何なのかを知るための特殊な変数なのです。

これを利用して「意図したとき」だけ動作するようにした例を実行してみます。まずはsample01.pyの改良版です。

sample03.py

#!/usr/bin/env python3.8

def sample():
	print(__name__)

if __name__ == "__main__":
	sample()

python04.py

#!/usr/bin/env python3.8

import sample03

print(__name__)

実行結果

$ python sample04.py 
__main__
$ 

上手くいきましたね。良い感じですね。__name__を見て__main__が返ってくる、返ってこないを利用してうまく制御できています。

さらに、sample04.pyを修正します。

sample05.py

#!/usr/bin/env python3.8

import sample03

if __name__ == "__main__":
	print(__name__)
	sample03.sample()

実行結果

$ python sample05.py 
__main__
sample03
$ 

そうですね。自分自身が単体で動作するときと他のスクリプトから呼び出されて再利用されるときで、両方ともに対応することが出来ています。

このように__name__という特殊な変数が用意されていることを利用して、プログラミングすることがあります。(もちろんしないこともたくさんあります)

# –*- coding: utf-8 –*-

続いては時折?見かける2行目のアレ、おまじないです。(最近は見かける機会がグッと減りましたね)

当サイトの記事で紹介しているソースコードには、この記事以外には全く登場しないと思います。そうですね、Python V3ではUTF-8がデフォルトになっているからです。テキストエディタの設定がUTF-8デフォルトになっているなら、もしくはPythonスクリプトはUTF-8で保存しているなら、必要が無いです。

それでも何なのかを知っておくのは豆知識というか、すこし気持ちのどこかに満たされる感覚があると思います。なので私の単なる自己満足ですが、それがこの記事を読んで下さった方の満足(他己満足)に繋がると思って記します。

そもそもの役割はすでに述べた通り「この先スクリプトを読み進めるに当たってUTF-8で読んでね!」ってPythonに教える物です。なのでデフォルトがUTF-8になっているので教えなくても良くなりました。

どこに書くべきかというと、2行目と信じて疑ってなかったころも私にはありましたが、仕様上は1行目か2行目に書くようにとされています。ということは書き方にも仕様があります。

#があってcodingの後は:=が許されて、値との間はタブやブランクが入っていてもOK。なので以下のような変な行でもOKです。

変な例1
    #                        coding=                                utf-8
変な例2
# このファイルは cording: utf-8 では書かれていません!!!!!!と嘘を書いてもダメです。

必要とされる条件は、以下の正規表現に合致すること。

^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)

そうですね、我々は?-*-なんてもっともらしい、さもお決まりのおまじないのごとく必要な文字だと騙されていたんです。

ということで、もしも書く必要性が生じたのであれば、とてもとても直感的に以下のように書いちゃって良いと思います。

# coding=shift_jis

なお、詳しくは以下に記載があります。

https://www.python.org/dev/peps/pep-0263/

ま、指定の仕方を間違って実行するとエラーメッセージにこのURLは表示されているんで、ご存じの方も多いかも知れません。