Category Archives: python

/usr/bin/env python3って何?

前提知識

スクリプトの最初の行の#!で始まるものはshebangと呼ばれる。

スクリプトを書いて、実行するときにシステムによってこの行が読まれ、この実行ファイルで当該スクリプトを実行する機能がLinux系のOSにはある。

pythonで実験

以下のファイルを作成 hello.py

実行してみる

python3を明示式に指定して実行すればちゃんと実行できるが、そうでない場合はbashとして実行されている事がわかる。

ここでshebangを加えてみる。

実行

ちゃんと実行できる。

pythonの特殊解釈

しかしpythonのスクリプトではshebangが/usr/bin/python3ではなく、/usr/bin/env python3と記述されている。

/usr/bin/envは引数を起動するだけのプログラムでオプションで環境変数を変更する機能がある。Linuxがこのshebangを読むと/usr/bin/env python3が起動してenvはをPATHなどから探してpython3を実行するものと思われる。

python3ではWindowsとの互換性のために/usr/bin/envがvirtual commandと解され、PATHからpython.exeを見つけるようになるのだと思う。

Windowsの場合は、python.exeの他にpy.exeがシステムディレクトリにインストールされているので、まずpy.exeがスクリプトのshebangを見て適切なpython実行ファイルを探して実行するものと思われる。

pythonのargparseの基本

pythonのargparseが難しいくて戸惑うので基本のもの

引数を取らないオプション

引数を1個とるオプション(デフォルト)

引数を1個とるオプション(個数指定)

0個か1個だけとるメイン(オプションのない)の引数

1個からN個とるメインの引数

nargsが+

0個からN個とるメインの引数

考察

ほかにもいろいろなことができるのだがやりすぎて使いにくくなってる感がある。基本を押さえと置けば理解もできるようになると思う。

python: 文字列はimmutableでリストはmutable

immutable

とは値を変えられないということ、というふうに言われるがpythonの場合は分かりづらい。
immutableとは変数の値が知らないところで書き換えられることがないことを示している。
文字列はimmutableと言われる。

C言語だと文字列はmutableになる。

pythonや多くの言語では上記のようなことはできず、文字列はimmutableになっている。

リストはmutable

mutableとは変数が知らないところで書き換わってしまうこと。

aとbは同じ実体を表すのでaに追加した4がbにも反映される。
しかし以下の場合は違う。

aに代入した[4,5,6]はもともとa,b両方が参照していたリストとは違うリストで新しく代入している。この場合はaとbは違うリストを参照している。
2つの変数が参照しているものが同じかどうかを調べるにはid()を使う。

文字列とリストでの関数の違い

しかし文字列でも同じid()を持つことはある。同じであってもそれが読み込みしかされていないなら問題はない。しかしそれを変更するわけにはいかないことから、このような違いは文字列とリストでの関数の違いとなって現れる。文字列の関数は常に新しい文字列を返し、自分自身を変更することはしない。リストの関数は常に自分自身を変更し、リストを返さない。

upper()は新しい文字列を返し、自分自身は変更しない。

append()は何も返さず、自分自身を変更する。

注意点

このようなふるまいからリストを使うときは注意を要することがある。

append()はリストを返さないのでlには何も入らない。以下のようにしないといけない。

pythonでcat

catコマンド

ファイルの中身を表示する

以下のようにしても動く

これは標準入力からファイルの内容を受け取りそれを出力している。

標準入力での切り分け

上記のことをpythonで実現するにはまず標準入力が普通の標準入力(キーボード)かパイプかを調べて処理を分ける。

ttyとはteleprinterのことで、昔あった手元にあるキーボードから遠くのプリンターに文字をタイプするマシンのことらしい。Linux界では接続されているキーボードをttyという概念で認識する。

ttyだった場合、引数にファイルがあればそれを表示し、なければ標準入力(キーボード)から入力を受け付ける。

ファイルの処理

パイプの処理

標準入力がキーボードで引数がない場合やパイプの場合はstdinから読み込む

これで大体動くが、catとの違いはキーボードから入力したときのエコーバックの時期が違う。catは1行ごとにエコーバックするが、このスクリプトの場合、Ctrl+D(Linux)やCtrl+Z(Windows)でEOFが送られるか、バッファがいっぱいになるまでwriteへ処理がいかない。よってこれを直す。

考察

キーボードとパイプの両方から入力を受け付けると便利なことが多い。スクリプトがjsonファイルを受け付けるとき、ユーザー側には他の形式のファイルがあってそれをjsonに変換してスクリプトの入力としたい時などパイプ入力がないといったんファイルに変換しないとならなくなる。

pythonでスクリプトのあるディレクトリにログファイルをつくる

__file__はスクリプトファイル、3.9以降では絶対パス、それ以前ではpythonに渡されたパスになるらしい。

realpathはシンボリックリンクなどを取り除いた絶対パスを返す。ほかにもabspathnormpathなどがある。

dirnameはディレクトリを返す。

splitextは拡張子で分割する。

この呼び出しにより、スクリプトと同じディレクトリにあって拡張子が.logのパスが得られる。

多数の似たようなSQLを実行したい場合pythonでSQLを出力するといい

多くの似たようなSQLを発行したい場合、例えばプログラムのfor文で回せば処理できるような場合どうすればいいか。一般にSQLはfor文はないから、pythonなどでスクリプトを書くのもいいかもしれない。がスクリプトでDBを開いてとか書くのが面倒。そこでpythonでSQLだけを出力して、それを実行してしまえばいい。

jupyter

こういうときのちょっとしたpythonスクリプトを書くにはjupyterが便利。
まずは1個のSQLをpythonのprintで出力してみる

次にfor文で回す。SQLはformatで置換する。

文字列中の{0:03}はformat引数の0番目の値を3桁で0で埋めることを指定している。これを実行すると以下のようなSQLが得られる。

あとはこれはphpMyAdminにコピペしたり、mysqlに直接流し込んでもいいかもしれない。DBの変更は間違うと大変なのでよくチェックしてから行おう。