Python Numpy① - 行列の作成

Numpyを使うとPythonで行列が簡単に扱えるようになります。

指定した大きさの配列を作成する

まず、以下のようにNumpyをインポートしておきます。

1
import numpy as np

ゼロ埋めの配列を作成する場合には下記のように書きます。

1
2
3
# 2行3列のゼロ埋めの配列を作成
x = np.zeros((2, 3))
print(x)

[実行結果]

[[ 0.  0.  0.]
 [ 0.  0.  0.]]

デフォルトではデータ型が numpy.float64 となりますがint型にしたい場合は、次のようにdtypeを指定します。
1
2
3
# 2行3列のゼロ埋めの配列を作成(int型)
x = np.zeros((2, 3), dtype=int)
print(x)

[実行結果]

[[0 0 0]
 [0 0 0]]

ゼロ埋めではなく 1埋めにしたい場合はnp.ones()メソッドを使用します。
1
2
3
# 2行3列の1埋めの配列を作成
x = np.ones((2, 3))
print(x)

[実行結果]

array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

Python - 順序付き辞書

Pythonの辞書型データは、キーと値をセットで管理でき記述方法も簡潔なのでとても便利なのですが、順序が保障されないため順番に管理したい場合に困ることがあります。

OrderedDictを使うと順序付きの辞書型としてデータを扱うことができます。

コード

OrderedDictを使うためには、まずimport文を記述する必要があります。
(ここが一般的な辞書型を使うよりも手間に感じます。)

1
2
3
4
5
6
7
8
9
10
from collections import OrderedDict

dict = OrderedDict()

dict['key1'] = 'value1'
dict['key2'] = 'value2'
dict['key3'] = 'value3'
dict['key4'] = 'value4'

print(dict)

実行結果

実行結果は次のようになります。

OrderedDict([('key1', 'value1'), ('key2', 'value2'), ('key3', 'value3'), ('key4', 'value4')])

辞書に追加した順でデータが並んでいることが分かります。

私が辞書型データを使う場合には、順番を考慮することが多いのでこのOrderedDictを標準の辞書型データとして欲しいくらいです。

Python fabric - 管理タスクの実行

アプリケーションのデプロイやシステム管理タスクを行うツールとしてfabicモジュールをご紹介します。

fabicモジュールを使うと、ローカルやリモートでのコマンド実行や、ファイルのアップロード・ダウンロードが簡単にできるようになります。

インストール

次のコマンドを実行しfabicをインストールします。

1
2
3
4
# インストール
pip install fabric3


コード

fabfile.pyを作成し、次のようなコードを書きます。ファイル名は必ずfabfile.pyにする必要があります。

4行目から7行目は環境に応じて設定して下さい。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from fabric.api import *

# 接続情報を設定
env.hosts = ['IPアドレス']
env.user = 'ユーザ名'
env.password = 'パスワード'
env.port = ポート番号

# タスクとなる関数を定義
# この関数名がfabコマンドを実行する際の引数になります。
def task1():
# ローカルでのコマンド実行
res = local('ipconfig')
print('res[{}]'.format(res)) # なぜか結果が格納されない

# コマンド実行
res = run('crontab -l')
print('res[{}]'.format(res))

# sudoでコマンド実行
res = sudo('crontab -l')
print('res[{}]'.format(res))

# ディレクトリを移動してコマンド実行
with cd('/tmp/'):
res = run('pwd')
print('res[{}]'.format(res))

# ファイルを転送する(ローカル → サーバ)
# *等を使ったパターン指定も可能
put('test.txt', '/var/samba/.')

# ファイルを受信する(サーバ → ローカル)
# *等を使ったパターン指定も可能
get('/var/samba/test.json', '.')

一通りの基本操作は上記のコードでカバーできていると思います。

コマンドの実行もファイル転送もとてもシンプルに書くことができます。

実行

動作を確認する場合は、fabコマンドにfabfile.py内の関数名を指定して実行します。

1
fab task1

Python - scp転送を行う

Pythonからscp転送を行ってみます。

scp転送とはssh通信を使ったファイル転送です。

インストール

Pythonからscp転送を行うためには paramikoscp というライブラリをインストールする必要があります。

1
2
pip install paramiko
pip install scp

コード

scp転送を行う最小コードは次のようになります。

11行目では環境に応じて、IPアドレス・ポート番号・ユーザ名・パスワードを設定してください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import scp
import paramiko

with paramiko.SSHClient() as ssh:
# 初回ログイン時に「Are you sure you want to continue connecting (yes/no)?」と
# きかれても問題なく接続できるように。
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# ssh接続する
print('[ssh接続]')
ssh.connect('[IPアドレス]', port=[ポート番号], username='[ユーザ名]', password='[パスワード]')

print('[SCP転送開始]')
# scp clientオブジェクト生成
with scp.SCPClient(ssh.get_transport()) as scp:
#
# SCP送信(ローカル → サーバ)
#
# ・同じファイルがあったら上書きされる。
# ・ディレクトリは指定できない。
scp.put('test.csv', '/var/samba/.')

#
# SCP受信(サーバ → ローカル)
#
# ・同じファイルがあったら上書きされる。
# ・ディレクトリは指定できない。
scp.get('/var/samba/mpv-shot0004.jpg', '.')

SCP送信する場合でも、SCP受信する場合でも、送信先に同じ名称のファイルがあると上書きされるので注意して下さい。

また、ディレクトリを指定することはできないので複数ファイルを送信する場合は、tarコマンドやzipコマンドを使って1ファイルにまとめてからscp転送する必要があります。

Python - ssh接続しコマンドを実行する

Pythonからssh接続を行いコマンドを実行する処理を行ってみます。

pythonからssh通信ができるようになると、複数サーバに同じコマンドを実行できたり、定期的にサーバ情報を取得し問題があったらアラートを発するなど監視ができるようになりとても便利です。

インストール

Pythonからssh接続を行うためには paramiko というライブラリをインストールする必要があります。

1
pip install paramiko

コード

ssh接続しコマンドを実行する最小コードは次のようになります。

9行目では環境に応じて、IPアドレス・ポート番号・ユーザ名・パスワードを設定してください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import paramiko

with paramiko.SSHClient() as ssh:
# 初回ログイン時に「Are you sure you want to continue connecting (yes/no)?」と
# きかれても問題なく接続できるように。
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# ssh接続
ssh.connect('[IPアドレス]', port=[ポート番号], username='[ユーザ名]', password='[パスワード]')

# コマンド実行
stdin, stdout, stderr = ssh.exec_command('ls -al')

# コマンド実行後に標準入力が必要な場合
# stdin.write('password\n')
# stdin.flush()

# 実行結果を表示
for o in stdout:
print('[std]', o, end='')
for e in stderr:
print('[err]', e, end='')

Python - 文字種(数字、アルファベットなど)の判定を行う

コーディングをしていると対象の文字列かどうかを判定する必要がある場合があります。

複雑な判定を行うときは正規表現で判定することになると思いますが、数字かどうか、アルファベットかどうかなど単純な文字列判定であれば標準で用意されている関数で十分です。

Python標準で用意されている文字種判定の関数を一覧にまとめてみました。

メソッド内容
.isalnum()文字列が全て英数文字かどうかを判定。
! や ? などの記号や空白文字が含まれている場合はFalse。
数字が含まれていてもTrue
空文字はFalse。
.isalpha()文字列が全て英文字かどうかを判定。
! や ? などの記号や空白文字が含まれている場合はFalse。
数字がふくまれていたらFalse
空文字はFalse。
.isdigit()文字列が全て数字かどうかを判定。
全角にも対応。
0から9までの数字のみTrue。
+ - (プラスマイナス)はFalse。
.isnumeric()文字列が全て数字かどうかを判定。
全角にも対応。
0から9までの数字とアラビア数字もTrue。
+ - (プラスマイナス)はFalse。
.islower()文字列が全て小文字かどうかを判定。
.isupper()文字列が全て大文字かどうかを判定。
.istitle()文字列がタイトルケース(単語の先頭が大文字)かどうかを判定。
.isspace()文字列が全て空白文字、タブ文字、改行文字のいずれかどうかを判定。
.isidentifier()文字列が変数として使用できるかどうかを判定。
(先頭がアルファベットまたは"_"で始まり、それ以降がアルファベット、数字、"_"のいずれかで埋まっていること)
.isprintable()文字列が全て表示可能な文字かどうかを判定。
空白文字はTrue。
タブ文字や改行文字が含まれていればFalse。

Python - CSVライブラリを使ったCSVファイル読み込み

Python3で標準機能として使えるCSVライブラリを用いてCSVファイルを読み込んでみます。

説明がいらないほど簡潔に書けます。

reader_test.py
1
2
3
4
5
6
import csv

with open('test.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
for row in reader: # 1レコードごとデータを読み込む
print(row) # フィールドを要素としたlistで表現される

入力用のCSVファイルは下記の通りです。

test.csv
1
2
3
4
city,year,season
London,2012,summer
Sochi,2014,winter
Rio,2016,summer

実行結果は次のようになります。

['city', 'year', 'season']
['London', '2012', 'summer']
['Sochi', '2014', 'winter']
['Rio', '2016', 'summer']

Python - CSVライブラリを使ったCSVファイル出力

Python3で標準機能として使えるCSVライブラリを用いてCSVファイルを出力します。

test.py
1
2
3
4
5
6
7
8
9
10
import csv

with open('test.csv', 'w') as csvfile:
writer = csv.writer(csvfile, lineterminator='\n')
# 見出し
writer.writerow(['city', 'year', 'season'])
# データ
writer.writerow(['London', 2012, 'summer'])
writer.writerow(['Sochi', 2014, 'winter'])
writer.writerow(['Rio', 2016, 'summer'])

4行目のlineterminatorでは改行コードを指定しています。

上記のコードを実行すると、次のようなCSVファイルが出力されます。

test.csv
1
2
3
4
city,year,season
London,2012,summer
Sochi,2014,winter
Rio,2016,summer

CSVライブラリを使わなくても、データをカンマ区切りでファイル出力すれば同じようにCSVファイルを出力することができると思いますが、CSVライブラリを使った方が簡潔にコードがかけているような気がします。

IME - 単語を登録する

名前や固有名詞、メールの定型文など、よく使う定型文は単語登録しておくと便利です。

登録したい単語を選択した状態で[Ctrl + F7]を押すと次のような「単語登録」画面が表示されます。

単語の登録


ここで読みや品詞を設定し、「登録」ボタンを押すと単語や定型文が登録できます。

登録が完了したら、登録した読みを入力して変換候補を表示してみます。

変換候補


登録した単語が変換候補に出てくることを確認できます。

ただ改行が入力できないのは残念なところです。

確認はできていませんが、IME2010のオープン拡張機能辞書を使えば改行を含めた定型文が登録できるそうです。

SikuliX - 目的の画像が表示されたら処理を行う(イベント処理)

SikuliXでGUI操作を自動化していると、イレギュラーな操作に対応しなければいけないことがあります。

例えば、ブラウザ操作でセキュリティ関連のダイアログがたまに表示されたり、認証ダイアログが表示されたりする場合です。

この場合、existsメソッドで対応することもできますがいつ表示されるかわらかない場合はあちこちにexists文を書かなくてはいけなくなり面倒です。

こんなときは、ある画像が表示されたときに操作を行うといったイベント処理を使うと便利です。

今回は、イベント処理を行う際に汎用的に使えるテンプレートを用意してみました。

SikuliXでイベント処理を行うテンプレート

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
region_center = Region(79,7,1746,976)   # 監視する画面範囲を設定

def hnd_security(event):
region_center.stopObserver() # 処理中に同じイベントが発生しないように監視を一旦止めておく
click("1576109569372-1.png") # なんらかの動作を行う
wait(2) # 短い時間に連続実行されないように少し時間をあけておく
region_center.observeInBackground() # 再度監視を始める

region_center.onAppear("1576109562192-1.png", hnd_security) # ある画像を見つけたらhnd_securityをコールする
region_center.observeInBackground() # 監視処理を始める

#
# 監視処理はバックグラウンドで行われているので
# ここでなにか他の処理を行うことが可能
#

# プログラム終了時
region_center.stopObserver() #監視処理を終了する。

イベント処理(監視処理)とは別にメイン処理を行いたい場合、observeInBackground(10行目)メソッドを使いバックグラウンドで監視処理を行う必要があります。

イベント発生時に実行される関数(イベントハンドラ)内では、画像が表示されている間に連続でコールされないように次のような工夫を行っています。

  • 最初にstopObserverで監視処理を一旦止めて、最後にobserveInBackgroundで監視処理を再開する。
  • 最後に監視処理を再開するまでに2秒待機させて、短い間にイベント処理が連続実行されないようする。

今回は、「イベントが何回も発生することがある」「2秒以内に同じ処理を実行してほしくない」というケースを想定して実装しましたが、目的に応じてコーディングする必要があると思います。

参考になれば幸いです。