技術メモ

役に立てる技術的な何か、時々自分用の覚書。幅広く色々なことに興味があります。

Pythonでコマンドライン引数を渡す方法3種類

Pythonコマンドライン引数を渡す方法は知る限り下記の3種類ある。
1. sys.argv
2. argparser
3. docopt

このうち、主に上の2つを紹介する。

sys.argv

最も簡単な方法。
コマンドラインの引数を配列のようにして扱う。

sample

import sys

print('script name : %s'%sys.argv[0])
print(sys.argv[1])
$ python parsers.py hello
script name : parsers.py
hello

使い方

sys.argsに配列としてコマンドライン引数が入っている。0番目はプログラムの名前に当たるので、1番目以降を引数として使うことになる。

argparser

sys.argvでは引数の個数も決めておかないといけないし順番もバラバラではいけない。
使い方がわからなくなったとしたら、ソースを読むしかない。
これに対してargparserではシェルのコマンドのように"--help"や"-h"を引数にすることでヘルプを表示させることができる。
また、引数の順番関係なくオプション指定で引数を渡すことができる(`-i hello -m 10`と`-m 10 -i hello`は同じ意味になる)
人に使ってもらうようなプログラムや大規模なプログラムを書くときはargparserを使うのが一番良いと思う。

sample

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int,
                    nargs='+',help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,help='sum the integers (default: find the max)')
parser.add_argument('--display',action='store_true')

args = parser.parse_args()
if(args.display):
    print('result :')
print(args.accumulate(args.integers))
$ python parsers.py 1 2 3 --display
result :
3

$ python parsers.py 1 2 3 --sum
6

$ python parsers.py -h
usage: parsers.py [-h] [--sum] [--display] N [N ...]

Process some integers.

positional arguments:
  N           an integer for the accumulator

optional arguments:
  -h, --help  show this help message and exit
  --sum       sum the integers (default: find the max)
  --display

使い方

大まかな使い方としては
1.パーサーを作る
2.引数を追加する
3.引数を解析する
という順番になっている。
詳しくは下のリンク先を見てもらうとして、
引数を追加するadd_parser()の引数だけ示しておく。

name または flags - 名前か、あるいはオプション文字列のリスト (例: foo や -f, --foo)。
action - コマンドラインにこの引数があったときのアクション。
nargs - 受け取るべきコマンドライン引数の数。
const - 一部の action と nargs の組み合わせで利用される定数。
default - コマンドラインに引数がなかった場合に生成される値。
type - コマンドライン引数が変換されるべき型。
choices - 引数として許される値のコンテナー。
required - コマンドラインオプションが省略可能かどうか (オプション引数のみ)。
help - 引数が何なのかを示す簡潔な説明。
metavar - 使用法メッセージの中で使われる引数の名前。
dest - parse_args() が返すオブジェクトに追加される属性名。

docopt

コメントにMarkdownドキュメントっぽく使い方を書いておけばそれをもとにオプション引数を作ってくれるという優れもの。
僕自身まだあまり馴染みがなく偉そうな事は書けないので、解説は下のリンクに譲る。
Pythonのdocopt使い方メモ - Qiita
Pythonのコマンドライン引数処理の決定版 docopt (あとJuliaに移植したよ) - りんごがでている

ASP, Saas, Paas, Iaas, Daasの具体例を挙げてみる。活用方法など。

クラウドの分類として用いられるSaas…etcなどの分類、言葉だけ聞くとあまりピンとこない。
実例を挙げることでイメージしやすくしてみた。
f:id:swdrsker:20180202042259p:plain*1

ASP, Saas

ASPはアプリケーションソフトの機能をネットワーク経由で顧客にサービスとして提供することであり、それを行っている事業者である。通常、利用者はブラウザソフトなどを使用してインターネットなどのネットワークを経由し、遠隔地からASPのサーバにアクセスすることで、そのサーバ内に格納された各種アプリケーションソフトの機能をサービスの形で利用する。
wikipedia: アプリケーションサービスプロバイダ

SaaS(サース、Software as a Service)は、必要な機能を必要な分だけサービスとして利用できるようにしたソフトウェア(主にアプリケーションソフトウェア)もしくはその提供形態のこと。一般にはインターネット経由で必要な機能を利用する仕組みで、シングルシステム・マルチテナント方式になっているものを指す
wikipedia: Saas

ASPSaasって何が違う?

説明を読むと、ん?何が違うの?って感じが、厳密な違いはないらしい。
ASPは事業者やビジネスモデルとしての意味合いが強く、Saasはサービスにフォーカスした言葉というニュアンスの違いだという。

具体例

Webブラウザ上で使うサービスは大体(全て?)Saasに当てはまる。

Paas

PaaSでは、ソフトウェアを構築および稼動させるための土台となるプラットフォームを、インターネット経由のサービスとして提供する。開発者は、プラットフォーム上で構築したサービスを自分の顧客に提供することができる。 具体的には、インフラ、DBMSユーザインタフェースなどのシステム開発手段となるツールや、開発したシステムを運用するための環境をインターネットを通じて「サービス」として提供し、月額使用料などの形で収入を得る事業モデルである
wikipedia: Paas

Iaas (Haas)

IaaS(Infrastructure as a Service の略。インターネットを利用したコンピュータの利用形態である。IaaSでは、コンピュータシステムを構築および稼動させるための基盤(仮想マシンやネットワークなどのインフラ)そのものを、インターネット経由のサービスとして提供する。
wikipedia: Iaas

Daas

DaaS は、Desktop as a Serviceの略で、その言葉のとおり個人用のデスクトップ環境をクラウド上に構築し、ネットワーク越しにその環境を呼び出して利用することを提供するサービスです。基本ソフトをはじめ全てのソフトやデータがネットワーク上のサーバーにあります。ユーザの端末は画面を表示する機能とキーボードなど操作に必要な機能だけあればよく、OSやアプリケーションソフトなどはすべてサーバ上で動作します。
DaaS(Desktop as a Service) | IoT

活用方法など【中級者以上向け】

この記事は面白い。

特に最近は人工知能ブームで機械学習や統計解析が盛んにおこなわれているが、その中で使うIoTでリアルタイムなデータを取ってきたりGPUAPIなんかを使いたい時にIaasやPaasを使うようだ。
データの管理やプログラムだけに集中したい時に重宝される。
経験上少し昔はそういった分析業務におけるクラウドAWS一強だった感じだが、Azureもそれなりに使われているらしい。

pythonでコードを書きながら楕円曲線暗号を理解する

仮想通貨についての勉強
楕円曲線暗号とは、ビットコインのデジタル署名で使われてる公開鍵暗号方式

この記事にあるコードを写経しながら勉強する。

自分自身まだ深く理解してないところがあるので解説は別の機会に書くことにしてメモ書き程度にとどめておく。

コード

from hashlib import sha256

class ECDSA:
    def __init__(self):
        # parameters are based on SPEC256k1
        self.cp = pow(2,256) - pow(2,32) - pow(2,9) - pow(2,8) - pow(2,7) - pow(2,6) - pow(2,4) - pow(2,0)
        self.cb = 7
        self.ca = 0
        self.base_x = 55066263022277343669578718895168534326250603453777594175500187360389116729240
        self.base_y = 32670510020758816978083085130507043184471273380659243275938904335757337482424
        self.base = (self.base_x, self.base_y)
        self.secret_key = None
        self.public_key = None

    def generate_key(self, string):
        secret_hash = sha256(string.encode('utf-8')).hexdigest()
        secret_key = int(secret_hash, 16)
        pt = self.EC_multi(secret_key)
        public_key = int("04" + "%064x" % pt[0] + "%064x" % pt[1], 16)
        self.secret_key = secret_key
        self.public_key = public_key
        return (public_key, secret_key)

    def EC_add(self, P, Q):
        lam = ((Q[1] - P[1]) * inv_mod(Q[0] - P[0], self.cp)) % self.cp
        x = ((pow(lam, 2)) - P[0] - Q[0]) % self.cp
        y = (lam * (P[0]- x) - P[1]) % self.cp
        return (x,y)

    def EC_double(self, P):
        lam = ((3 * (pow(P[0], 2) + self.ca) * inv_mod(2 * P[1], self.cp))) % self.cp
        x = (pow(lam, 2) - 2*P[0]) % self.cp
        y = (lam * (P[0] - x) - P[1]) % self.cp
        return (x,y)

    def EC_multi(self, scalar):
        if scalar == 0:
            raise ValueError('invalid scalar/ purivate key')
        scalar_bin = str(bin(scalar))[2:]
        point = self.base
        for i in range(1, len(scalar_bin)):
            point = self.EC_double(point)
            if scalar_bin[i] == "1":
                point = self.EC_add(point, self.base)
        return point

def inv_mod(k, mod):
    return pow(k, mod-2, mod)


if __name__=="__main__":
    ecdsa = ECDSA()
    pk, sk = ecdsa.generate_key("Satoshi Nakamoto")
    print(sk)
    print(pk)

(補足)モジュラ逆数

モジュラ逆数とはa^{-1}\equiv x \pmod{m}となるxのこと。
素数 mと互いに素な aに対して

 a^{-1}\equiv a^{m-2} \pmod{m}

となることを使っている。(フェルマーの小定理

(証明)
オイラー関数 \phi(m)を用いて、mが素数の時
\displaystyle
\left\{
\begin{array}{1}
 a^{\phi(m)}\equiv 1 \pmod{m}\\
 \phi(m) = m-1 
\end{array}
\right .
なので

a^{\phi(m) - 1} \equiv a^{-1} \pmod{m} \\
a^{m-2} \equiv a^{-1} \pmod{m}
(Q.E.D)

pythonでは a^{m-2}\pmod{m}

pow(a, m-2, m)

の1行で書ける