「Python tips」の版間の差分

提供: Eospedia
移動: 案内検索
(pickle)
(build-in)
 
(同じ利用者による、間の15版が非表示)
行12: 行12:
 
=== 引数個数の指定 ===
 
=== 引数個数の指定 ===
 
https://docs.python.org/release/3.8.2/library/argparse.html#nargs
 
https://docs.python.org/release/3.8.2/library/argparse.html#nargs
 +
 +
==== 一つ以上のキーワード引数 ====
 +
<pre>
 +
parser.add_argument('--hoge', nargs='+', help='Hoge files')
 +
</pre>
 +
パース結果はリストに格納される。
  
 
=== ヘルプメッセージにデフォルト値を表示する ===
 
=== ヘルプメッセージにデフォルト値を表示する ===
行17: 行23:
 
<pre>
 
<pre>
 
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 +
</pre>
 +
 +
=== スニペット1 ===
 +
<pre>
 +
def parse_args():
 +
    parser = argparse.ArgumentParser(
 +
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
 +
        description=__doc__
 +
    )
 +
 +
    args = parser.parse_args()
 +
 +
    print('##### Command #####\n\t' + ' '.join(sys.argv))
 +
    args_print_str = '##### Input parameters #####\n'
 +
    for opt, val in vars(args).items():
 +
        args_print_str += '\t{} : {}\n'.format(opt, val)
 +
    print(args_print_str)
 +
    return args
 
</pre>
 
</pre>
  
行39: 行63:
 
     args = parser.parse_args()
 
     args = parser.parse_args()
  
     logger.info('##### Command #####\n\t' + ' '.join(sys.argv))
+
     print('##### Command #####\n\t' + ' '.join(sys.argv))
 
     args_print_str = '##### Input parameters #####\n'
 
     args_print_str = '##### Input parameters #####\n'
 
     for opt, val in vars(args).items():
 
     for opt, val in vars(args).items():
 
         args_print_str += '\t{} : {}\n'.format(opt, val)
 
         args_print_str += '\t{} : {}\n'.format(opt, val)
 +
    print(args_print_str)
 
     return args
 
     return args
 
</pre>
 
</pre>
行91: 行116:
 
with open(pickled_file, 'rb') as f:
 
with open(pickled_file, 'rb') as f:
 
     pickled_content = pickle.load(f)
 
     pickled_content = pickle.load(f)
 +
</pre>
 +
 +
== subprocess ==
 +
=== run - 同期型 ===
 +
<pre>
 +
ret = subprocess.run("シェルコマンド", text=True, shell=True, capture_output=True)
 +
</pre>
 +
 +
投げたシェルコマンドが終わるまで呼び出し側コードはブロックされる。
 +
 +
retが持つ属性は ret.args, ret.returncode, ret.stdout, ret.stderr。
 +
 +
=== Popen - 非同期型 ===
 +
* 参考
 +
** https://qiita.com/HidKamiya/items/e192a55371a2961ca8a4
 +
** https://qiita.com/megmogmog1965/items/5f95b35539ed6b3cfa17
 +
<pre>
 +
p = subprocess.Popen("シェルコマンド", shell=True, text=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
 +
</pre>
 +
 +
Popenはコマンド投げっぱなしで、呼び出し側コードは遠慮なく先へ進む。
 +
 +
処理の終了 (p.poll() is not None)を待ちつつ、出力をリアルタイム表示するには、例えば以下の様にする。
 +
<pre>
 +
while True:
 +
    if p.poll() is not None:
 +
        break
 +
    line = p.stdout.readline()
 +
    if line is not None:
 +
        print(line, end='')
 +
</pre>
 +
 +
== datetime ==
 +
* datetimeはモジュール名、datetime.datetimeはdatetimeモジュールのdatetimeクラス
 +
=== タイムスタンプ文字列生成 ===
 +
20201119-093428 などのフォーマットで年月日-時刻の文字列を生成するには、
 +
<pre>
 +
import datetime
 +
datetime.datetime.now().strftime('%Y%m%d-%H%M%S')
 +
</pre>
 +
nowはクラスメソッドで、現在時刻を持ったインスタンスを生成する。
 +
 +
=== iso8601フォーマットで時刻表示 ===
 +
isoformatメソッドを使う。例えば、
 +
<pre>
 +
In [6]: a = datetime.datetime.strptime('2020/11/19 18:55:37.614', '%Y/%m/%d %H:%M:%S.%f')
 +
 +
In [7]: a.isoformat()
 +
Out[7]: '2020-11-19T18:55:37.614000'
 +
</pre>
 +
 +
=== 任意の型式の日時表示からdatetimeインスタンス生成 ===
 +
strptimeメソッドを使う。例えば、
 +
<pre>
 +
In [5]: datetime.datetime.strptime('2020/11/19 18:55:37.614', '%Y/%m/%d %H:%M:%S.%f')
 +
Out[5]: datetime.datetime(2020, 11, 19, 18, 55, 37, 614000)
 +
</pre>
 +
どうやらミリ秒は無くて、マイクロ秒(%fでパース)で表現するらしい。
 +
 +
== docstring ==
 +
=== モジュールdocstring ===
 +
ファイルの先頭にそのモジュールの説明を書けばよい。
 +
<pre>
 +
'''Hoge fuga module
 +
 +
This module is for hoge fuga piyo!'''
 +
</pre>
 +
 +
シェバン行やエンコーディング指定はモジュールdocstringの前に書く。
 +
<pre>
 +
#!/usr/bin/env python
 +
# *_* coding: utf-8 *_*
 +
 +
'''Hoge fuga module
 +
 +
This module is for hoge fuga piyo!'''
 +
</pre>
 +
 +
モジュールdocstringは<pre>__doc__</pre>で参照できる。
 +
 +
== build-in ==
 +
=== print ===
 +
==== 改行無しで表示 ====
 +
<pre>
 +
print('hogefuga', end='')
 +
</pre>
 +
 +
=== 型チェック ===
 +
==== isinstance ====
 +
<pre>
 +
isinstance(obj, class_or_tuple)
 
</pre>
 
</pre>

2020年11月19日 (木) 13:51時点における最新版

argparse

https://docs.python.org/release/3.8.2/library/argparse.html

インスタンス化

モジュールdocstring書いといてそれをdescriptionにすると良さげ

parser = argparse.ArgumentParser(description=__doc__)

オプション名の書き方と格納先変数名

https://docs.python.org/release/3.8.2/library/argparse.html#dest

引数個数の指定

https://docs.python.org/release/3.8.2/library/argparse.html#nargs

一つ以上のキーワード引数

parser.add_argument('--hoge', nargs='+', help='Hoge files')

パース結果はリストに格納される。

ヘルプメッセージにデフォルト値を表示する

https://docs.python.org/release/3.8.2/library/argparse.html#argparse.ArgumentDefaultsHelpFormatter

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)

スニペット1

def parse_args():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description=__doc__
    )

    args = parser.parse_args()

    print('##### Command #####\n\t' + ' '.join(sys.argv))
    args_print_str = '##### Input parameters #####\n'
    for opt, val in vars(args).items():
        args_print_str += '\t{} : {}\n'.format(opt, val)
    print(args_print_str)
    return args

具体例1

def parse_args():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description=__doc__
    )
    parser.add_argument('--Z_file', type=str, required=True, help='Pickled file of latent variables.')
    parser.add_argument('--k_init', type=int, default=2, help='Initial number of clusters in X-Means')
    parser.add_argument('--k_max', type=int, default=20, help='Max number of clusters in X-Means')
    parser.add_argument('--criterion', type=str, default='bic', choices=['bic', 'mndl'], help='Splitting criterion. bic: bayesian information criterion, mndl: minimum noiseless description length.')
    parser.add_argument('--random_state', type=int, default=None, help='Random seed for X-Means initialization (K-Means++)')
    parser.add_argument('--no_ccore', action='store_true', help='Use python implementation of PyClustering library, instead of C++.')
    parser.add_argument('--outdir', required=True, help='Output directory.')
    parser.add_argument('--input_star', type=str, required=True, help='Input star file.')
    parser.add_argument('--output_star_rootname', type=str, default='cluster', help='Output file rootname for each cluster\'s star file.')
    parser.add_argument('--output_model', type=str, default='xmeans_model.pkl', help='Output X-Means model file name (pickled).')

    args = parser.parse_args()

    print('##### Command #####\n\t' + ' '.join(sys.argv))
    args_print_str = '##### Input parameters #####\n'
    for opt, val in vars(args).items():
        args_print_str += '\t{} : {}\n'.format(opt, val)
    print(args_print_str)
    return args

logging

https://docs.python.org/release/3.8.2/library/logging.html

ロガー生成スニペット

logging_fmt = logging.Formatter(
    '\n[%(asctime)s - %(name)s - %(levelname)s] %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(logging_fmt)
logger.addHandler(stream_handler)


def set_logger(log_file, is_debug):
    if log_file is not None:
        log_file_dir = os.path.dirname(log_file)
        if log_file_dir:
            if not os.path.exists(log_file_dir):
                logger.debug('Creating log file directory...')
                os.makedirs(log_file_dir)
            elif not os.path.isdir(log_file_dir):
                logger.error('{} is not a directory.'.format(log_file_dir))
                sys.exit(1)
        file_handler = logging.FileHandler(log_file, mode='w')
        file_handler.setFormatter(logging_fmt)
        logger.addHandler(file_handler)

    if not is_debug:
        logger.setLevel(logging.INFO)

serialize

pickle

保存

pickle.dump(\
    object_to_be_serialized,
    open(outfile, 'wb'),
    protocol=4)

読み込み

with open(pickled_file, 'rb') as f:
    pickled_content = pickle.load(f)

subprocess

run - 同期型

ret = subprocess.run("シェルコマンド", text=True, shell=True, capture_output=True)

投げたシェルコマンドが終わるまで呼び出し側コードはブロックされる。

retが持つ属性は ret.args, ret.returncode, ret.stdout, ret.stderr。

Popen - 非同期型

p = subprocess.Popen("シェルコマンド", shell=True, text=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

Popenはコマンド投げっぱなしで、呼び出し側コードは遠慮なく先へ進む。

処理の終了 (p.poll() is not None)を待ちつつ、出力をリアルタイム表示するには、例えば以下の様にする。

while True:
    if p.poll() is not None:
        break
    line = p.stdout.readline()
    if line is not None:
        print(line, end='')

datetime

  • datetimeはモジュール名、datetime.datetimeはdatetimeモジュールのdatetimeクラス

タイムスタンプ文字列生成

20201119-093428 などのフォーマットで年月日-時刻の文字列を生成するには、

import datetime
datetime.datetime.now().strftime('%Y%m%d-%H%M%S')

nowはクラスメソッドで、現在時刻を持ったインスタンスを生成する。

iso8601フォーマットで時刻表示

isoformatメソッドを使う。例えば、

In [6]: a = datetime.datetime.strptime('2020/11/19 18:55:37.614', '%Y/%m/%d %H:%M:%S.%f')

In [7]: a.isoformat()
Out[7]: '2020-11-19T18:55:37.614000'

任意の型式の日時表示からdatetimeインスタンス生成

strptimeメソッドを使う。例えば、

In [5]: datetime.datetime.strptime('2020/11/19 18:55:37.614', '%Y/%m/%d %H:%M:%S.%f')
Out[5]: datetime.datetime(2020, 11, 19, 18, 55, 37, 614000)

どうやらミリ秒は無くて、マイクロ秒(%fでパース)で表現するらしい。

docstring

モジュールdocstring

ファイルの先頭にそのモジュールの説明を書けばよい。

'''Hoge fuga module

This module is for hoge fuga piyo!'''

シェバン行やエンコーディング指定はモジュールdocstringの前に書く。

#!/usr/bin/env python
# *_* coding: utf-8 *_*

'''Hoge fuga module

This module is for hoge fuga piyo!'''
モジュールdocstringは
__doc__
で参照できる。

build-in

print

改行無しで表示

print('hogefuga', end='')

型チェック

isinstance

isinstance(obj, class_or_tuple)