前回は下記リンクからご覧ください。
Pythonのよく使う標準ライブラリ一覧と使い方の例 その2
argparseでCLIの引数を管理する
argparse
はコマンドラインインタフェースを作成するためのPython標準ライブラリモジュールです。プログラムが必要とする引数を定義し、sys.argv
からそれらの引数を解析する方法を見つけ出すプロセスを簡略化できます。
パーサを作成する
argparse
でパーサーを作成することはコマンドライン引数を管理するための最初のステップです。パーサーを初期化し、必要な引数を追加します。引数には、オプションと位置指定(必須)があります。以下はパーサーを作成し、オプションの引数を追加する例です。
import argparse
# パーサーを作成
parser = argparse . ArgumentParser ( )
# 引数を追加
parser . add_argument ( '--name' , default = '名無し' , help = '名前を入力してください。' )
# 引数をパース
args = parser . parse_args ( )
print ( f"こんにちは、 { args . name } !" )
この例ではオプションの引数--name
を用意しています。ユーザーがこの引数を指定しない場合、そのデフォルト値名無し
が使用されます。
位置決め引数
オプションの引数とは別に、argparse
では位置指定(必須)の引数を指定できます。オプションの引数とは異なり、位置指定引数は--name
のような名前を前に付ける必要がありません。先ほどのスクリプトを修正して、必須の位置引数を入れてみましょう。
import argparse
# パーサーを作成
parser = argparse . ArgumentParser ( )
# 引数を追加
parser . add_argument ( 'location' , help = 'お住まいの地域を入力してください。' )
# 引数をパース
args = parser . parse_args ( )
print ( f"あなたは { args . location } に住んでいます。" )
ここで、location
は必須引数です。ユーザがこの引数を与えなかった場合、argparse
はエラーメッセージを表示しスクリプトはそれ以上進みません。
getoptで引数取得を便利にする
Pythonのgetopt
モジュールは、コマンドラインのオプションと引数を解析するもう1つの方法です。argparse
と同様にユーザーフレンドリーなコマンドラインインターフェイスを作成するのにも役立ちます。getopt
モジュールはsys.argv[1:]
を処理し、オプション、引数などのペアのリストとオプション以外の引数のリストを返します。
getoptの基本的な使い方
getopt
を使うには期待するオプションを定義する必要があります。getopt.getopt
関数は、解析するコマンドライン引数(通常はsys.argv[1:]
)、ショートオプション、ロングオプションの3つの引数を取ります。ショートオプションにはダッシュが1つ付き、グループ化できます。ロングオプションは先頭にダッシュが2つ付いています。以下は簡単な例です。
import getopt
import sys
short_options = "ho:v"
long_options = [ "help" , "output=" , "verbose" ]
try :
arguments , values = getopt . getopt ( sys . argv [ 1 : ] , short_options , long_options )
except getopt . error as err :
print ( str ( err ) )
sys . exit ( 2 )
for current_argument , current_value in arguments :
if current_argument in ( "-v" , "--verbose" ) :
print ( "enabling verbose mode" )
elif current_argument in ( "-h" , "--help" ) :
print ( "displaying help" )
elif current_argument in ( "-o" , "--output" ) :
print ( ( "enabling output mode (%s)" ) % ( current_value ) )
上のコードでは、h
、o:
、v
が短いオプション(o
の後のコロンは引数が必要という意味)、help
、output=
、verbose
が長いオプションとなります。
高度なgetoptの使い方
特定のオプションに引数を要求するように指定できます。getopt
に渡すオプション文字列では上のo
オプションに見られるように、引数を必要とするオプションはコロンを付ける必要があります。以下に、この使い方の例を示します。
import getopt
import sys
short_options = "o:"
long_options = [ "output=" ]
try :
arguments , values = getopt . getopt ( sys . argv [ 1 : ] , short_options , long_options )
except getopt . error as err :
print ( str ( err ) )
sys . exit ( 2 )
for current_argument , current_value in arguments :
if current_argument in ( "-o" , "--output" ) :
print ( ( "output file is (%s)" ) % ( current_value ) )
このコードではo
オプションは引数を必要とし、出力ファイルの名前を示しています。このスクリプトをコマンドラインから実行し、-o output.txt
または--output output.txt
を含めると出力されます。出力ファイルはoutput.txt
と表示されます。
loggingでログメッセージを操作する
logging
モジュールは、ソフトウェアの実行時に発生するイベントを追跡するための強力な組み込みPythonライブラリです。Pythonプログラムからログメッセージを出力するための柔軟なフレームワークを提供します。print
文を使うよりも堅牢で柔軟性があり、ログを分類したり、ログメッセージのレベルに基づいて何をすべきかを決定したり、といったいくつかの利点があります。ここではlogging
モジュールを使用する簡単な例を示します。
import logging
# コンソールに表示されます
logging . warning ( 'This is a warning message' )
上記の例ではlogging
モジュールをインポートし、logging.warning()
を呼び出して警告メッセージを表示させています。logging
モジュールはイベントの重大性を示す5つの標準レベルを定義しています。DEBUG、INFO、WARNING、ERROR、CRITICALです。
loggingの基本設定
logging
モジュールを効果的に使用するためにログメッセージのレベルやフォーマットを指定する設定が可能です。basicConfig(**kwargs)
メソッドを使ってlogging
の設定できます。
import logging
logging . basicConfig ( level = logging . DEBUG ,
format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' )
logging . warning ( 'これは警告文です' )
上のコードでは、レベルをDEBUGに設定していますが、これはこのレベル以上のものをキャプチャすることを意味します。また、ロギング時刻、ロガー名、重大度レベル、メッセージを含むように形式を設定しています。
ファイルへのログ
コンソールにメッセージを表示するだけでなくログ出力をファイルに出力可能です。これは長時間プログラムを実行し、後でログを分析したい場合に便利です。ここではメッセージをファイルに記録する方法を説明します。
import logging
logging . basicConfig ( filename = 'app.log' ,
level = logging . WARNING ,
format = '%(name)s - %(levelname)s - %(message)s' )
logging . warning ( 'これは警告文です' )
上記のコードでは、basicConfig
メソッドのfilename
パラメータを使ってログファイルの名前を指定しています。ログメッセージはapp.log
に書き込まれます。レベルをWARNINGにすることで、WARNING以上のイベントのみをログへ記録するようにしています。
getpassでパスワード入力を取り入れる
Pythonのgetpass
モジュールは、ユーザーのパスワードやその他の機密情報を管理する際に便利なツールです。主に、パスワードのような機密性が要求されるユーザー入力を扱うために、ユーザーが入力した内容をコンソール上でエコーしないよう使用します。ここでは、getpass
の使い方を説明します。
import getpass
user = getpass . getuser ( )
password = getpass . getpass ( 'Please enter your password: ' )
print ( f'User: { user } , Password: { "*" * len ( password ) } ' )
この例ではgetpass
モジュールをインポートし、getuser()
でユーザーのログイン名を取得し、getpass()
でユーザーにパスワードを表示させずに尋ねています。
getpassによるパスワード処理
getpass
モジュールの主な使用例はPythonプログラムでのパスワード処理です。これにより、ユーザは他人に見られる心配をすることなく、機密情報を入力できます。これは入力された各文字をアスタリスク(*
)に置き換えたり、単に何も表示しないことで実現されます。
import getpass
password = getpass . getpass ( "パスワードを入力してください: " )
print ( "あなたのパスワードは" , '*' * len ( password ) )
上記のコードスニペットでは、getpass.getpass()
を使用してユーザーのパスワードを尋ねています。ユーザーが入力しても表示されません。
プラットフォーム固有の動作
getpass
モジュールについて注意すべき点はその動作がプラットフォームによって異なる場合があることです。Unixではechoをオフにし、Windowsではパスワードダイアログを使用します。安全な入力ができない状況ではgetpass
は警告を出す可能性があります。
import getpass
try :
password = getpass . getpass ( )
except Exception as error :
print ( 'ERROR:' , error )
else :
print ( 'Password entered:' , password )
この例ではgetpass
の使用で発生する可能性のある例外を安全な方法で処理します。
Pythonのplatform
モジュールは、ハードウェア、オペレーティングシステム、インタプリタのバージョン情報など、基盤となるプラットフォームのデータへアクセスするために使用します。これはコードの中でプラットフォームに依存した判断をする必要がある場合や、異なるプラットフォーム間でデバッグを行う場合に役立つことがあります。
import platform
print ( platform . system ( ) )
print ( platform . release ( ) )
このコードでは、platform.system()
は、Linux
、Windows
、Darwin
のようにオペレーティングシステムの名前を返します。platform.release()
関数はシステムのリリースバージョンを返します。
platform
モジュールは実行中のPythonのバージョンやビルド番号など、Pythonインタプリタ自体の詳細も知ることができます。
import platform
print ( platform . python_version ( ) )
print ( platform . python_build ( ) )
このスニペットでは、python_version()
はPythonのバージョンを文字列として提供し、python_build()
はビルド番号と日付を文字列として含むタプルを返しています。
ハードウェア情報へのアクセス
さらにplatform
モジュールはハードウェア情報にアクセスできます。これにはマシンタイプやプロセッサ情報などのデータが含まれ、ハードウェアによって実行経路が異なるスクリプトには非常に便利です。
import platform
print ( platform . machine ( ) )
print ( platform . processor ( ) )
この例ではplatform.machine()
は、i386
のようなマシンタイプを返します。platform.processor()
関数はシステムのプロセッサについてのより具体的な情報を提供します。
threadingでマルチスレッドを操作する
Pythonのthreading
モジュールはマルチスレッドプログラミングのために使用されます。スレッドとは、オペレーティングシステムで同時に実行できる最小の実行単位です。マルチスレッドの主な利点は、複数のタスクが互いに干渉することなく同時に実行できるようになることです。
import threading
def print_numbers ( ) :
for i in range ( 10 ) :
print ( i )
def print_letters ( ) :
for letter in 'abcdefghij' :
print ( letter )
thread1 = threading . Thread ( target = print_numbers )
thread2 = threading . Thread ( target = print_letters )
thread1 . start ( )
thread2 . start ( )
上記のコードでは、threading.Thread()
を使って2つのスレッドを作成し、それぞれ関数print_numbers()
とprint_letters()
に関連付けしています。スレッドはstart()
メソッドで開始されます。
スレッドを同期させる
スレッドは独立して実行できますが、時には実行を同期させる必要があります。そのための1つの方法として、スレッドモジュールのLock
オブジェクトを使用します。
import threading
lock = threading . Lock ( )
def print_numbers ( ) :
lock . acquire ( )
for i in range ( 10 ) :
print ( i )
lock . release ( )
def print_letters ( ) :
lock . acquire ( )
for letter in 'abcdefghij' :
print ( letter )
lock . release ( )
thread1 = threading . Thread ( target = print_numbers )
thread2 = threading . Thread ( target = print_letters )
thread1 . start ( )
thread2 . start ( )
この例ではacquire()
メソッドがLock
オブジェクトをロックし、1つのスレッドだけが一度にコードブロックを実行できるようにします。実行が完了したら、release()
メソッドを呼び出してLock
オブジェクトのロックを解除し、他のスレッドが処理を進められるようにします。
スレッドセーフとグローバルインタープリタロック
Pythonのスレッド化によって特定の種類のプログラムを高速化できますが、GILがあるため、すべてのPythonコードをスレッド化によって高速に動作するわけではないことを知っておくことが重要です。GILは1つのプロセスで同時に1つのスレッドしかPythonバイトコードを実行できない仕組みで、CPUバウンドプログラムではスレッド化による性能が制限されることもあります。
import threading
import time
def slow_operation ( ) :
time . sleep ( 5 ) # これはIOバウンド操作です
thread1 = threading . Thread ( target = slow_operation )
thread2 = threading . Thread ( target = slow_operation )
thread1 . start ( )
thread2 . start ( )
このコードではslow_operation()
はIOバウンド操作(入出力を待つ操作、この場合はsleep
)です。待機中はGILが解放されるため、この間に他のスレッドが実行できるようになります。つまり、PythonにGILがあってもIOバウンドのタスクではスレッド化によって大幅な高速化が可能なのです。
multiprocessingでマルチプロセスを操作する
Pythonのmultiprocessing
モジュールは、プロセスを作成でき、ローカルおよびリモートの同時実行を提供します。プロセスとはプログラム(Pythonインタプリタなど)のインスタンスであり、システム内でタスクを実行するものです。multiprocessing
モジュールはPythonの複数スレッドの実行を制限するGIL (Global Interpreter Lock)を克服するのに有効です。
from multiprocessing import Process
def print_numbers ( ) :
for i in range ( 5 ) :
print ( 'Number:' , i )
def print_hello ( ) :
for _ in range ( 5 ) :
print ( 'Hello' )
if __name__ == '__main__' :
process1 = Process ( target = print_numbers )
process2 = Process ( target = print_hello )
process1 . start ( )
process2 . start ( )
process1 . join ( )
process2 . join ( )
上記のコードでは別々のプロセスで実行される2つの関数print_numbers
とprint_hello
を定義しています。
プロセス間のデータ共有
プロセス間のデータ共有はスレッディングとは異なる方法で行われます。multiprocessing
モジュールでは、プロセス間でデータを共有するためにValue
やArray
を用意しています。以下は簡単な例です。
from multiprocessing import Process , Value
def add_100 ( number ) :
for _ in range ( 100 ) :
number . value += 1
if __name__ == '__main__' :
shared_number = Value ( 'i' , 0 )
process1 = Process ( target = add_100 , args = ( shared_number , ) )
process2 = Process ( target = add_100 , args = ( shared_number , ) )
process1 . start ( )
process2 . start ( )
process1 . join ( )
process2 . join ( )
print ( shared_number . value )
両方のプロセスがアクセスし変更できる整数を保存するために共有されたValue
を使用しています。
プールを使ってプロセスを管理する
multiprocessing
では、プロセス間の通信経路としてQueue
とPipe
の2種類、プロセス作成APIとしてProcess
とPool
の2種類をサポートしています。Pool
はワーカーのプールで使用するプロセスを一定数作成したい場合に使用します。以下は簡単な例です。
from multiprocessing import Pool
def square ( number ) :
return number * number
if __name__ == '__main__' :
numbers = [ 1 , 2 , 3 , 4 , 5 ]
with Pool ( ) as p :
results = p . map ( square , numbers )
print ( results )
このコードでは、ワーカープロセスのプールを作成し、map
関数を使って関数とイテラブルを各プロセスにマッピングしています。
concurrentで非同期実行する
Pythonのconcurrent.futures
モジュールは、非同期で実行される関数のための高レベルのインターフェイスを提供します。このモジュールは、非同期I/O、タスクスケジューリング、プロセスプール、スレッドプールを実装しています。シンプルかつ使いやすいAPIでスレッドやプロセスを使ってタスクを同時実行できます。
以下に、簡単な使用例を示します。
from concurrent . futures import ThreadPoolExecutor
import time
def task ( message ) :
time . sleep ( 2 )
return message
pool = ThreadPoolExecutor ( max_workers = 5 )
future = pool . submit ( task , ( "Completed Task" ) )
print ( future . result ( ) )
このコードでは、ThreadPoolExecutor
を使ってワーカーのプールを作成し、このプールにタスクを投入してFuture
インスタンスを返します。future.result()
は、タスクが完了するまでブロックしてから結果を返します。
map関数を使う
map
関数はリストなどの反復可能な項目のすべてに関数を適用して、その結果のリストを返す組み込み関数です。concurrent.futures
でも利用可能で、同じ概念を適用しますが同時並行的に実行されます。
from concurrent . futures import ThreadPoolExecutor
def task ( n ) :
return n * 2
with ThreadPoolExecutor ( max_workers = 4 ) as executor :
results = executor . map ( task , [ 1 , 2 , 3 , 4 , 5 ] )
for result in results :
print ( result )
このコードでは、map
関数がリストの各項目にタスク関数を同時に適用しています。
ProcessPoolExecutorを使う
CPUに負荷のかかるタスクを実行する必要がある場合、PythonのスレッドはGILの影響を受けるため、マルチスレッドではなくマルチプロセシングを使用する方がよいです。concurrent.futures
モジュールはこのためにProcessPoolExecutor
クラスを提供します。
from concurrent . futures import ProcessPoolExecutor
def task ( n ) :
return n * 2
with ProcessPoolExecutor ( max_workers = 4 ) as executor :
results = executor . map ( task , [ 1 , 2 , 3 , 4 , 5 ] )
for result in results :
print ( result )
このコードは、ThreadPoolExecutor
を使った前の例と同様に動作しますが、スレッドの代わりにプロセスを使用し、複数のCPUやコアを利用してGILによる制限を回避できます。
subprocess
Pythonのsubprocess
モジュールは、新しいプロセスを生成し、その入力/出力/エラーパイプに接続し、その結果をコードを取得できる強力なツールです。os.system
, os.spawn
, os.popen
など、いくつかの古いモジュールや関数を置き換えることを意図しています。
以下に基本的な使い方の例を示します。
import subprocess
# UNIXコマンド'ls'を実行するための新しいプロセスを起動
process = subprocess . run ( [ 'ls' ] , stdout = subprocess . PIPE )
# 結果を表示
print ( process . stdout . decode ( ) )
subprocess.run()
関数は引数のリストを受け取ります。リストの最初の項目はコマンドで、残りの項目はコマンドのパラメータです。この場合、コマンドls
はパラメータを持ちません。
エラー処理とプロセス通信
subprocess
は失敗することがあります。エラーをコードで正しく処理することが重要です。subprocess
が失敗すると0
以外の完了ステータスが返されます。check=True
引数をsubprocess.run()
関数に渡すと、subprocess
で失敗したときに例外を発生させることができます。
import subprocess
try :
subprocess . run ( [ 'ls' , 'non_existent_file' ] , check = True )
except subprocess . CalledProcessError :
print ( "'ls'コマンドが失敗しました" )
このスクリプトは存在しないファイルのリストを作成しようとします。ls
コマンドは失敗し、0
以外の完了ステータスを返すため、subprocess.run()
はCalledProcessError
例外を発生させています。
より複雑なユースケースでPopenを使う
より複雑なユースケースにはPopen
クラスを使用できます。このクラスはより柔軟で、新しいプロセスを起動し、その入力/出力/エラーパイプへ接続するために使用できます。これは入出力データが大きすぎてメモリに収まらない場合や、プロセスの実行中に対話する必要がある状況で有用です。
import subprocess
# 新しいプロセスを起動
process = subprocess . Popen ( [ 'grep' , 'python' ] , stdin = subprocess . PIPE , stdout = subprocess . PIPE )
# プロセスに入力値を送る
stdout , _ = process . communicate ( b'pythonたのしい\njavaもたのしい\n' )
# 結果を出力
print ( stdout . decode ( ) )
このスクリプトは、grep
プロセスを生成し入力値を送っています。grep
コマンドはpython
という単語を含んでいない行をフィルタリングします。
queueでキューを操作する
queue
は複数のスレッド間で安全に情報をやり取りする必要があるスレッドプログラミングにおいて、特に有用なマルチプロデューサー/マルチコンシューマーキューを実装しています。基本的なqueue
はFIFO(First In, First Out)動作を提供します。
以下は、キューを使用する簡単な例です。
import queue
# 新しいキューを作成
q = queue . Queue ( )
# キューに要素を追加
q . put ( 'apple' )
q . put ( 'banana' )
q . put ( 'cherry' )
# キューから要素を削除
print ( q . get ( ) ) # 'apple'
print ( q . get ( ) ) # 'banana'
このコードでは、まずqueue.Queue()
を使って新しいキューを作成します。次にput()
メソッドでキューに要素を追加します。最後にget()
メソッドで要素を削除して出力します。
queueのメソッドとプロパティ
queue
モジュールのQueue
クラスにはいくつかの便利なメソッドとプロパティがあります。put()
とget()
の他に、empty()
、full()
、qsize()
メソッドを提供しています。
import queue
q = queue . Queue ( 2 ) # サイズが2のキューを作成
print ( q . empty ( ) ) # キューが空の場合はTrue
q . put ( 'apple' )
print ( q . full ( ) ) # キューのサイズが満杯ではないのでFalse
q . put ( 'banana' )
print ( q . full ( ) ) # キューのサイズが満杯なのでTrue
print ( q . qsize ( ) ) # キューのサイズ確認
上のコードではQueue()
コンストラクタに最大サイズが与えられています。empty()
はキューが空かどうか、full()
はキューがいっぱいかどうかをチェックし、qsize()
はキューの現在の大きさを返します。
スレッドでキューを使う
queue
はスレッドと同時に実装することが多いです。以下の例では、アイテムをキューに入れるプロデューサースレッドと、キューからアイテムを取得するコンシューマースレッドを生成しています。
import queue
import threading
def producer ( q ) :
for i in range ( 5 ) :
q . put ( i )
print ( f'Produced: { i } ' )
def consumer ( q ) :
while True :
item = q . get ( )
print ( f'Consumed: { item } ' )
q . task_done ( )
q = queue . Queue ( )
t1 = threading . Thread ( target = producer , args = ( q , ) )
t2 = threading . Thread ( target = consumer , args = ( q , ) )
t1 . start ( )
t2 . start ( )
q . join ( ) # すべてのタスク完了までブロックする
このコードではproducer()
関数がアイテムをキューに入れ、consumer()
関数がキューからアイテムを取得します。q.join()
メソッドはキュー内のすべてのアイテムが取得され処理されるまでブロックされます。
asyncioで並列実行する
Pythonのasyncio
ライブラリは標準ライブラリの一部です。コルーチンを使ってシングルスレッドの並行コードを書いたり、ソケットや他のリソースでのI/Oアクセスを多重化したり、サブプロセスのネットワークを管理するインフラを提供します。スレッドやプロセスを使うよりも読みやすく、理解しやすい非同期コードを書くことができるようになります。
ここではasyncio
を使ってタスクを並行して実行する簡単な例を紹介します。
import asyncio
async def hello ( ) :
print ( 'Hello,' )
await asyncio . sleep ( 1 )
print ( 'world!' )
# イベントループを作成
loop = asyncio . get_event_loop ( )
# hello関数を2回並行実行
loop . run_until_complete ( asyncio . gather ( hello ( ) , hello ( ) ) )
# ループを閉じる
loop . close ( )
このコードでは両方のタスクからHello,
と表示され、1秒待って両方のタスクからWorld!
と表示されます。
コルーチンとタスクの基本
asyncio
の核となるのはコルーチンです。コルーチンはPythonのジェネレータ関数に特化したもので、returnへ達する前に実行を中断し、間接的に別のコルーチンへしばらく制御を渡すことができます。
タスクはコルーチンを同時にスケジュールする状況で使用されます。タスクが作成されるとすぐ実行されるようにスケジュールされます。
以下はその例です。
import asyncio
async def count ( ) :
print ( "One" )
await asyncio . sleep ( 1 )
print ( "Two" )
async def main ( ) :
await asyncio . gather ( count ( ) , count ( ) , count ( ) )
asyncio . run ( main ( ) )
この例では非同期関数count()
を定義し、asyncio.gather()
を使ってmain()
関数内で3回同時実行しています。
高度なasyncioの機能
asyncio
では、サーバーやクライアントの作成、ロックやセマフォの管理など、高度な機能もサポートされています。たとえば、次のような簡単なエコーサーバーを作成できます。
import asyncio
async def echo ( reader , writer ) :
data = await reader . read ( 100 )
message = data . decode ( )
addr = writer . get_extra_info ( 'peername' )
print ( f"Received { message } from { addr } " )
print ( f"Send: { message } " )
writer . write ( data )
await writer . drain ( )
writer . close ( )
async def main ( ) :
server = await asyncio . start_server ( echo , '127.0.0.1' , 8888 )
addr = server . sockets [ 0 ] . getsockname ( )
print ( f'Serving on { addr } ' )
async with server :
await server . serve_forever ( )
asyncio . run ( main ( ) )
このコードではポート8888
でlocalhostサーバを起動し、受信したデータをすべてエコーバック(ユーザーに対し状態を表示すること)するサーバーを定義しています。サーバーはasyncio.start_server()
で起動し、例えばKeyboardInterrupt
などで停止するまで動作します。
sslで安全に通信する
デジタル時代の今日、データや通信の安全性を確保することは最も重要なことです。そこで登場するのがSSL(Secure Sockets Layer)です。SSLはネットワークに接続されたコンピュータ間で認証され、暗号化されたリンクを確立するためのプロトコルです。Pythonは標準ライブラリにssl
モジュールを提供しており、これは安全なソケット通信するためのソケットオブジェクトのTLS/SSLラッパーです。
import ssl
import socket
context = ssl . create_default_context ( )
with socket . create_connection ( ( 'www.python.org' , 443 ) ) as sock :
with context . wrap_socket ( sock , server_hostname = 'www.python.org' ) as ssock :
print ( ssock . version ( ) )
上記のコードではssl.create_default_context()
関数を使用して、プロトコル、証明書など、SSLのデフォルト設定をしています。次にsocket.create_connection()
を使用して、ポート443
のホストwww.python.org
への接続を作成します。context.wrap_socket()
は通常のソケットをSSLでラップするために使用されます。
sslモジュールの使用例
基本的な接続を設定するだけでなく、ssl
モジュールはSSL関連のタスクを処理するための多くの機能性を提供してくれます。例えば、このモジュールを使ってSSLクライアントとサーバーの両方を作成できます。プロトコルや暗号など、様々なパラメータを要件に応じて指定できます。
import ssl
import socket
context = ssl . SSLContext ( ssl . PROTOCOL_TLSv1_2 )
context . verify_mode = ssl . CERT_REQUIRED
context . load_verify_locations ( 'ca_certs' )
with socket . create_connection ( ( 'www.python.org' , 443 ) ) as sock :
with context . wrap_socket ( sock , server_hostname = 'www.python.org' ) as ssock :
print ( ssock . version ( ) )
上記のコードではssl.SSLContext()
を使用して、特定の設定を持つSSLコンテキストを作成しています。新しいコンテキストで使用するSSLバージョンとして、ssl.PROTOCOL_TLSv1_2
を設定しています。また、証明書を要求する検証モードにはssl.CERT_REQUIRED
をセットしています。他のピアの証明書を検証するために使用するCA(認証局)証明書のセットを読み込むにはcontext.load_verify_locations('ca_certs')
をセットします。
sslモジュールを使う有用性
ssl
モジュールの使い方を学ぶことでアプリケーションの安全性を確保できるため大きなメリットがあります。PythonでSSLを理解し管理することは、上記で示したように比較的簡単です。
import ssl
import urllib . request
context = ssl . SSLContext ( ssl . PROTOCOL_TLSv1_2 )
context . verify_mode = ssl . CERT_REQUIRED
context . load_verify_locations ( 'ca_certs' )
https_handler = urllib . request . HTTPSHandler ( context = context )
opener = urllib . request . build_opener ( https_handler )
urllib . request . install_opener ( opener )
response = urllib . request . urlopen ( 'https://www.python.org/' )
print ( response . read ( ) )
この例ではssl
モジュールを使ってコンテキストを作成し、それをPythonのurllib.request
で使って安全なHTTPSリクエストを作成しています。この例ではssl
を他のPythonモジュールと組み合わせて使用することで、安全な接続できることを示しています。
signalでプロセス送受信を操作する
信号処理は信号の操作と分析を含む広大で魅力的なテーマです。コンピュータの文脈では、シグナルとはあるイベントが発生したことをプロセスに通知するものです。Pythonのsignal
モジュールを使うとプログラムでシグナルを使ったり扱ったりできます。シグナルハンドラを設定したり、シグナルを無視したりするために使用されるPythonのライブラリの不可欠な部分です。
import signal
import time
def signal_handler ( signum , frame ) :
print ( 'Signal handler called with signal' , signum )
signal . signal ( signal . SIGINT , signal_handler )
while True :
time . sleep ( 1 )
上記のコードでは、シグナルを処理するための関数signal_handler
を定義しています。そしてこの関数をSIGINT
(通常はControl+Cで発生する)のハンドラとしてsignal.signal()
を使って登録しています。このプログラムを実行し、Control+C
を押すと、プログラムが終了するのではなくシグナルハンドラが呼び出されます。
Signalモジュールの使用例
signal
モジュールは単にハンドラを設定するだけではありません。シグナルを送信したり、シグナルを受信するまでプログラムの実行を一時停止したり、アラームシグナルを管理したりとさまざまな用途に使用できます。
import signal
import time
def signal_handler ( signum , frame ) :
print ( 'Signal handler called with signal' , signum )
signal . signal ( signal . SIGALRM , signal_handler )
signal . alarm ( 5 )
while True :
time . sleep ( 1 )
この例ではSIGALRM
を処理するシグナルハンドラを登録しています。次にsignal.alarm(5)
を使用して、5秒後にプロセスへ送信されるアラームシグナルをスケジュールしています。シグナルを受信するとハンドラが起動されます。
Signalモジュールを使うメリット
signal
モジュールはプログラムの流れを制御し、システムイベントに反応する新しい方法を開きます。これは、非同期タスク、タイムアウト、特定の条件下でのプログラムの実行の中断を扱うときに重要です。Pythonプログラマーなら誰でも知っておくべき強力なツールです。
import signal
import sys
def exit_gracefully ( signum , frame ) :
print ( "Exiting gracefully..." )
sys . exit ( 1 )
signal . signal ( signal . SIGINT , exit_gracefully )
while True :
pass
この最後の例ではSIGINT
を受信したときにプログラムを優雅に終了させるハンドラーを登録します。突然プログラムを終了させるのではなく、プログラムが終了する前にクリーンアップする方法を提供しています。これはsignal
モジュールを使用して、予期せぬイベントをエレガントに処理する堅牢なアプリケーションを構築する方法の基本例です。
jsonでJSONデータを操作する
JSON(JavaScript Object Notation)形式は、そのコンパクトさと読みやすさからデータ交換のためにWeb上で広く使用されています。Pythonはjson
モジュールを使うことでJSONデータを扱うことができるようになります。json.dumps()
メソッドでPythonオブジェクトをJSON文字列に変換(シリアライズ)し、json.loads()
でJSONデータをオブジェクトにデコード(デシリアライズ)できます。
import json
# Pythonの辞書型
data = {
"name" : "John" ,
"age" : 30 ,
"city" : "New York"
}
# JSONへ変換
json_data = json . dumps ( data )
print ( json_data )
上記の例ではPython辞書をjson.dumps()
メソッドでJSON文字列に変換しています。出力はJSON形式の文字列となります。
JSONでファイルを操作する
json
モジュールにはJSONデータをファイルへ読み書きするためのメソッドも用意されています。json.dump()
関数はPythonオブジェクトをJSONとしてファイルに書き込み、json.load()
はJSONファイルをPythonオブジェクトに読み返します。
import json
# Pythonの辞書型
data = {
"name" : "John" ,
"age" : 30 ,
"city" : "New York"
}
# JSONデータ書き込み
with open ( 'data.json' , 'w' ) as f :
json . dump ( data , f )
# JSONデータ読み込み
with open ( 'data.json' , 'r' ) as f :
data = json . load ( f )
print ( data )
ここではまずjson.dump()
を使ってPython辞書をファイルdata.json
に書き込みます。次に同じファイルを開き、json.load()
を使ってデータをPythonオブジェクトに読み返します。
JSONを扱うメリット
JSONデータを扱えることは特にAPIやWebアプリケーションを扱うプログラマーにとって重要なスキルです。Pythonのjson
モジュールを使えば、JSONデータの解析やPythonのデータ構造のJSONへの変換が簡単にできます。辞書やリストだけでなく、文字列、数値、ブーリアン値、None、さらに複雑な型もサポートしており、Pythonの武器として汎用性の高いツールを提供します。
import json
# 複雑なオブジェクト
data = {
"name" : "Taro" ,
"age" : None ,
"married" : True ,
"divorced" : False ,
"children" : ( "Hanako" , "Jiro" ) ,
"pets" : None ,
"cars" : [
{ "model" : "Mazda" , "mpg" : 27.5 } ,
{ "model" : "Toyota" , "mpg" : 24.1 }
]
}
# JSONへ変換
json_data = json . dumps ( data )
print ( json_data )
最後の例ではより複雑なPythonオブジェクトがJSON文字列に変換されています。このようにPythonのjson
モジュールは強力で直感的に使うことができます。
続きは下記リンクからご覧ください。
Pythonのよく使う標準ライブラリ一覧と使い方の例 その4