パスワード生成スクリプトをきっかけにoptparseを使ってみました
会社ではPerlで使い捨てスクリプトを書いたり、書かなかったりしているbonlifeです。id:nullpobugさんのパスワード生成スクリプトを参考にさせていただき、Pythonの標準モジュール「optparse」を使うサンプルを書いてみました。使い慣れておいて、ちょっとしたツールを作る時にサッと使いたいところですね。ということで、早速スクリプトです。(色々と追記してしまったので、ちょっとだけ長めです。)
- gen_passwd.py
import sys import string import random from optparse import OptionParser allowed_chars = (string.letters + string.digits).translate(string.maketrans('',''),'lO0') def gen_pass_core(passlen): password = '' for i in range(passlen): password += allowed_chars[random.randrange(len(allowed_chars))] return password def gen_pass(passlen,strong): if strong: if passlen < 3: raise Exception, 'password length should be larger than 3' while True: password = gen_pass_core(passlen) if (password.isalpha() == False and password.isdigit() == False and password.isupper() == False and password.islower() == False): return password break else: return gen_pass_core(passlen) def main(): usage = "usage: %prog [options] length count" version = "%prog 1.0" parser = OptionParser(usage=usage,version=version) parser.add_option("-s","--strong",action="store_true",dest="strong",help="generate strong password") (options, args) = parser.parse_args() if len(args) != 2: parser.print_help() exit() passlen = int(args[0]) count = int(args[1]) for i in range(count): print gen_pass(passlen,options.strong) if __name__ == "__main__": main()
少しだけ説明です。
まず、パスワードに使える文字列の生成です。文字列リテラルで直接定義しても全く問題ないのですが、Pythonクックブックの1章を読んで覚えたてのstringモジュールの定数などを使ってみました。translateを使って指定した文字列を削除したり。
続いて、本題のoptparse。何かしらoptionを定義しないとつまらないので、引数を取らない -s (--strong) というオプションを付けてみることにしました。
parser.add_option("-s","--strong",action="store_true",dest="strong",help="generate strong password") (options, args) = parser.parse_args()
上記のようにすると、-s あるいは --strong が指定された場合に、action の store_true が効いて、options.strong が True になります。これを利用して、gen_pass() の部分で強制的にstrongなパスワードにするかどうかを制御します。(help で指定した文字列は、引数に -h あるいは --help が指定された場合に使われます。)
次は、strong を強制する場合の処理について説明します。
if (password.isalpha() == False and password.isdigit() == False and password.isupper() == False and password.islower() == False): return password
見ていただければ分かると思いますが、アルファベットのみではなく、数字のみでもなく、大文字のみでもなく、小文字のみでもない場合に、はじめてreturnしています。(これで本当にstrongか、というのは気にしない方向で。あくまでもオプションを指定する練習です。) この条件に当てはまるまで、外側の while ループで何度も繰り返しています。この処理を追加した結果、パスワード文字列が3文字以上でなければ、passwordがreturnされず、永遠にループされてしまうことになりました。そこで、以下のように例外を発生させることに。
if strong: if passlen < 3: raise Exception, 'password length should be larger than 3'
本当は、Exceptionクラスを継承した独自の例外クラスを定義して、その例外をraiseした方が良いのかもしれませんが、今回はとりあえず止まれば良いや、的な発想で、素のExceptionを使ってみました。
そんなこんなで完成したスクリプトの使い方は以下の通りです。
C:\test\python>python gen_passwd.py --version gen_passwd.py 1.0
C:\test\python>python gen_passwd.py 8 3 whbRu5he gcZCtrHT BEvFZfAd
C:\test\python>python gen_passwd.py -s 8 3 ExY3WXwm r8xyacH4 V66WGn6R
C:\test\python>python gen_passwd.py -s 2 3 Traceback (most recent call last): File "gen_passwd.py", line 48, in <module> main() File "gen_passwd.py", line 45, in main print gen_pass(passlen,options.strong) File "gen_passwd.py", line 17, in gen_pass raise Exception, 'password length should be larger than 3' Exception: password length should be larger than 3
毎日Pythonに触れていると、少しずつ手に馴染んでくる気がする今日この頃です。