Pythonプログラムをマインクラフトのチャット入力エリアから実行する際に、もしパラメータの入力不足が発生した場合にチャットメッセージで親切なエラーメッセージを表示するプログラムを解説します。
エラー処理やif文による動きの切り分けについては前回の記事で紹介していますので、まだ見ていない方はこちらからご覧ください。
パラメータの1つ1つが正しいかを確認
今回のプログラムは、前回同様に3個のパラメータを指定してコマンドを実行します。
そして、3個それぞれのパラメータに指定モレがないか、そしてちゃんと数字で指定されているかを検査し、もしエラーがあった場合は何個めのパラメータに問題があるのかをチャットメッセージでお知らせするPythonプログラムを作ってゆきます。
それではPythonプログラムを見てみましょう。
ご自身の環境で動かしてみたい場合は、以下の場所に保存してください。
ファイルパス(Macの場合)
/Users/ユーザ名/Library/Application Support/minecraft/mcpipy/road4.py
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# coding: UTF-8 # 上のコードを書くことで、日本語のコメントを有効にします # ここから事前準備: 与えられた値が数字かどうかを検査する機能 def is_integer(data): mc.postToChat('is_integer機能で、値「' + str(data) + '」の検査をします') # ここから: 試します try: # 与えられた値を整数(数字データ)に変換してみます int(data) # エラーが出なかったら、この機能を呼出した場所に True(成功しました!!) を返します return True # 整数の変換でエラーが出てしまったら except ValueError: # この機能を呼出した場所に False(ダメでした…) を返します return False # ここまで: 試します # ここまで事前準備: 与えられた値が数字かどうかを判断する機能 # マインクラフト用のプログラムを読み込みます from mine import * # sysというプログラムを読み込みます import sys # マインクラフト用のプログラムを、すぐに使えるように「mc」として準備します mc = Minecraft() # チャットメッセージを出力します mc.postToChat("road4.py の処理を開始します") # プログラムを実行するときに指定された値を取得します params = sys.argv # ここから: 指定された値が正しいかを調べます try: # パラメータが4個指定されているかを確認します # 1個め、params[0] には実行するプログラムのファイル名が入っています # 2個め、params[1] には道のブロック数が入っています # 3個め、params[2] には道の幅が入っています # 4個め、params[3] には道の種類が入っています if not 4 == len(params): # もしパラメータが3個指定されていなかった場合、エラー処理に移動します raise ValueError ('このコマンドは3個のパラメータが必要です') # パラメータの1個めが数字で指定されているかを、先に作っておいた「is_integer」機能で確認します if False == is_integer(params[1]): # もしパラメータの1個めが数字ではなかった場合、エラー処理に移動します raise ValueError ('パラメータの1個め、道のブロック数は数字で指定してください') # パラメータの2個めが数字で指定されているかを、先に作っておいた「is_integer」機能で確認します if False == is_integer(params[2]): # もしパラメータの2個めが数字ではなかった場合、エラー処理に移動します raise ValueError ('パラメータの2個め、道の幅は数字で指定してください') # パラメータの3個めが数字で指定されているかを、先に作っておいた「is_integer」機能で確認します if False == is_integer(params[3]): # もしパラメータの2個めが数字ではなかった場合、エラー処理に移動します raise ValueError ('パラメータの3個め、ブロックの種類は数字で指定してください') except ValueError as e: # チャットメッセージを出力します mc.postToChat('エラーが発生しました') mc.postToChat(e) # エラーメッセージの内容を出力します mc.postToChat('プログラムを途中で終了します') # プログラム停止 sys.exit() # ここまで: パラメータで指定された値が正しいかを調べます # ここまでの処理でエラーが発生しなかった場合に、以下の処理に進みます # チャットメッセージを出力します mc.postToChat('パラメータのエラーはありませんでした') # ここから: 受け取ったパラメータを整理します # 道のブロック数を、プログラム実行時に指定された値に設定します length_number = int(params[1]) # 道の幅を、プログラム実行時に指定された値に設定します road_width = int(params[2]) # ブロックの種類を、プログラム実行時に指定された値に設定します block_number = int(params[3]) # ここまで: 受け取ったパラメータを整理します # チャットメッセージを出力します mc.postToChat(str(length_number) + 'ブロックの道を作ります') mc.postToChat('道の幅は' + str(road_width) + 'です') mc.postToChat('ブロックの種類は' + str(block_number) + 'です') # 道の幅が1個多く作られてしまうので、ここで調整 road_width = road_width - 1 # 自分の位置情報を取得します # 取得してきた位置情報は、それぞれ変数 x, y, z に保存されます x,y,z = mc.player.getPos() # 繰り返し命令を実行します # 繰り返す回数は length_number で指定した数ぶん for i in range(length_number): # i には何回めの繰り返し回数かが記録されています # ただし i はゼロから開始されるので、チャットメッセージには i+1 の値を出力します mc.postToChat(str(i+1) + "ブロックめの道を作ります") # i ブロックめの道を作ります mc.setBlocks(x+i, y-1, z, x+i, y-1, z+road_width, block_number) # 繰り返し命令はここで終了です # 繰り返し命令から抜け出すと、以下の実行が始まります mc.postToChat("道を" + str(i+1) + "ブロック作りました") mc.postToChat("実行終了です") |
わざと正しく動かないパラメータを指定して実行した結果、このようなチャットメッセージが出力されるようになりました。
def を使い、事前に機能を用意する
今回のプログラムで注目してほしい点は、まず最初に「機能」を用意しているということ。
機能とは、ある決められた処理や計算をひとまとまりにして置いておき、いつでも好きなタイミングでその「機能」を何回も呼び出して使うことができるものです。
今回用意する機能は、「ある値が数字データなのか、それ以外なのか」を検査するもので、パラメータに指定された値が正しいものかを判断するために利用します。
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# ここから事前準備: 与えられた値が数字かどうかを検査する機能 def is_integer(data): mc.postToChat('is_integer機能で、値「' + str(data) + '」の検査をします') # ここから: 試します try: # 与えられた値を整数(数字データ)に変換してみます int(data) # エラーが出なかったら、この機能を呼出した場所に True(成功しました!!) を返します return True # 整数の変換でエラーが出てしまったら except ValueError: # この機能を呼出した場所に False(ダメでした…) を返します return False # ここまで: 試します # ここまで事前準備: 与えられた値が数字かどうかを判断する機能 |
上のコードを日本語に翻訳してみると、
- 「is_integer」という名前の機能を準備します
- チャットメッセージで “is_integer機能で、値「(この機能に渡された値)」の検査をします” と出力します。
- ここから試します
- 与えられた値を int という命令を使って整数(数字データ)に変換してみます
- もし問題なく変換できたら整数(数字データ)なので、機能の呼び出し元に True(成功しました!!)と結果を返します
- もし整数への変換が失敗したらエラーが発生するので、機能の呼び出し元に False(ダメでした…)と結果を返します
- 機能を終了します
といった内容になり、機能 is_integer に何かしらの値を1個与えることでその値が数字であるかを検査し、その結果を呼び出し元に返します。
今までのPythonプログラムでは、プログラムが上から下へ順番に実行されるものでしたが、「def」というプログラムからはじまる機能を使うことで、実行される場所が突然違う場所に移動するようになったので驚きますよね。
事前に用意した def の機能を呼び出し、結果を得る
そして呼び出し元では以下のコードが書かれていて、if文を使って is_integer の結果がどうだったかを確認し、動作分けをおこなっています。
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# パラメータの1個めが数字で指定されているかを、先に作っておいた「is_integer」機能で確認します if False == is_integer(params[1]): # もしパラメータの1個めが数字ではなかった場合、エラー処理に移動します raise ValueError ('パラメータの1個め、道のブロック数は数字で指定してください') # パラメータの2個めが数字で指定されているかを、先に作っておいた「is_integer」機能で確認します if False == is_integer(params[2]): # もしパラメータの2個めが数字ではなかった場合、エラー処理に移動します raise ValueError ('パラメータの2個め、道の幅は数字で指定してください') # パラメータの3個めが数字で指定されているかを、先に作っておいた「is_integer」機能で確認します if False == is_integer(params[3]): # もしパラメータの2個めが数字ではなかった場合、エラー処理に移動します raise ValueError ('パラメータの3個め、ブロックの種類は数字で指定してください') |
もし機能「is_integer」の結果が「False(ダメでした…)」だった場合にだけif文の中に入り、そこでエラーを発生させていますよね。
エラーを発生させるときに、どのようなエラー内容なのかをカッコ内に書いている点にも注目する必要があります。
56 |
raise ValueError ('パラメータの1個め、道のブロック数は数字で指定してください') |
のプログラムが実行されると、エラー処理「except」の部分に括弧内の文章が渡されてチャットメッセージ出力されています。
69 70 71 72 73 74 75 76 |
except ValueError as e: # チャットメッセージを出力します mc.postToChat('エラーが発生しました') mc.postToChat(e) # エラーメッセージの内容を出力します mc.postToChat('プログラムを途中で終了します') # プログラム停止 sys.exit() |
その他のPythonプログラムの解説については、以前の記事をたどって参考にしてみてくださいね。
その他の関数の例
def で事前に用意しておく機能のことを、プログラマは「関数」と呼んでいます。
今までのプログラムで出てきた以下のPythonプログラムも、事前に準備された機能を呼び出している「関数」です。
マインクラフト用に用意されている、チャットメッセージを出力する関数
mc.postToChat()
マインクラフト用に用意されている、プレーヤの位置を取得する関数
mc.player.getPos()
Pythonプログラムで最初から用意されている、値を数字(整数)データに変換する関数
int()
Pythonプログラムで最初から用意されている、値を文字データに変換する関数
str()
sys という名前の道具箱の中に入っている exit() という名前の機能で、プログラムを終了する関数
sys.exit()
など。
Python ではじめから用意されている機能もあれば、
from mine import *
import sys
などのプログラムで、外部に用意してある道具箱を手元に呼び寄せ、道具箱の中に入っている機能を手軽に使うという方法もあります。
この道具箱は、ほかにも
import datetime
import time
import random
などがあるので、今後の記事で使い方を少しずつ紹介してゆきます。