v0.10.0への移行¶
v0.10.0は、ライブラリの根本的動作が大幅に変更された、ライブラリの中でも大きな更新の一つです。
最大の大きな変更点はPython 3.4.2以前のすべてのバージョンのサポートが打ち切られたことです。これは asyncio
をサポートするためで、対応する in the corresponding issue で詳細が見られます。繰り返しになりますが、 Python 2.7及びPython3.3は、既にサポートされていません 。
以下は、v0.9.0からv0.10.0までのその他の主要な変更点です。
イベント登録¶
以前まではすべてのイベントが Client.event()
を使用して登録されていました。このやり方はまだ可能ですが、 @asyncio.coroutine
で修飾が必要です。
更新前:
@client.event
def on_message(message):
pass
更新後:
@client.event
@asyncio.coroutine
def on_message(message):
pass
Python 3.5以降の場合:
@client.event
async def on_message(message):
pass
多くの型付けがあるため、登録を簡単にするためにユーティリティデコレータ (Client.async_event()
) が用意されています。例:
@client.async_event
def on_message(message):
pass
しかし、これはまだコルーチンであり、コルーチンである関数には @asyncio.coroutine
あるいは async def
での修飾が必要であることに注意してください。
イベントの変更¶
v0.9.0でいくつかのイベントは、別の状態を持たないために、役に立たないと考えられていました。変更された主なイベントは、更新前と更新後の二つの状態を持つ _update
イベントです。
更新前:
def on_channel_update(channel): pass
def on_member_update(member): pass
def on_status(member): pass
def on_server_role_update(role): pass
def on_voice_state_update(member): pass
def on_socket_raw_send(payload, is_binary): pass
更新後:
def on_channel_update(before, after): pass
def on_member_update(before, after): pass
def on_server_role_update(before, after): pass
def on_voice_state_update(before, after): pass
def on_socket_raw_send(payload): pass
on_status
が削除されていることに注意してください。似たような機能が使いたい場合は、 on_member_update()
を使用します。詳細は イベントリファレンス を参照してください。他に、 on_socket_closed
、 on_socket_receive
や on_socket_opened
も削除されています。
コルーチン¶
ライブラリの最大の変更点は Client
を使用していたほとんどの関数が コルーチン へと変更されたことです。ドキュメントのコルーチンとして定義された関数は、処理の終了を待機します。例えば、
更新前:
client.send_message(message.channel, 'Hello')
更新後:
yield from client.send_message(message.channel, 'Hello')
# or in python 3.5+
await client.send_message(message.channel, 'Hello')
yield from
あるいは await
を使用するには、関数が @asyncio.coroutine
または async def
で修飾されている必要があります。
イテラブル¶
パフォーマンス上の理由から、より高速な情報の取得を可能とするため、多くの内部データ構造が辞書に変更されました。結果として、これはAPIを介して公開された一部リストが、シーケンスではなくイテラブルに変更されたことを意味します。つまるところ、現在、特定の属性はイテラブルのみをサポートしており、シーケンスを扱うことができないことを意味しています。
影響を受ける属性は以下のとおりです。
Client.servers
Server.channels
Server.members
以前は有効であったが、現在は無効である操作の例。
if client.servers[0].name == "test":
# do something
これらは、既に list
ではないため、インデックスや反復処理以外の操作はサポートされなくなりました。以前の動作で処理を行うには、listに明示的にキャストする必要があります。
servers = list(client.servers)
# work with servers
警告
構造の内部的な変更のため、データを受け取った順序は保証されません。
列挙型¶
Python 3.4.2以前のバージョンのサポートを打ち切ったため、ライブラリは理にかなった場所での enum — Support for enumerations の使用が可能になりました。
変更された主な場所は、サーバーリージョン、メンバーのステータス、およびチャンネルタイプです。
更新前:
server.region == 'us-west'
member.status == 'online'
channel.type == 'text'
更新後:
server.region == discord.ServerRegion.us_west
member.status = discord.Status.online
channel.type == discord.ChannelType.text
この変更の主な理由は、APIでの厄介な文字列の使用を削減することでした。ユーザーに誤った感覚を与える可能性があったためです。詳細は 列挙型 を参照してください。
プロパティ¶
定数値を返す関数呼び出しの多くは、書式化した文字列での使いやすさ向上を図るため、Pythonのプロパティに変更されました。
以下はプロパティに変更された関数です。
変更前 |
変更後 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
メンバー管理¶
BANやキックを含む関数が追加されました。
変更前 |
変更後 |
|
|
|
|
関数の改名¶
いくつかの関数名が変更されました。
変更前 |
変更後 |
|
|
すべての Permissions
関連の属性の名称が変更され、 接頭詞であった can_ が削除されました。例を挙げると can_manage_messages
が manage_messages
になりました。
強制キーワード引数¶
Python 3.0以降では、強制的にキーワード引数をとるようにすることができるようになりました。キーワード引数は、変数の名前を明示的に指定してそれに割り当てることで、例えば foo(name='test')
などです。このサポートにより、ライブラリ内のいくつかの関数が変更され、キーワード引数を取るようになりました。これは引数の順序が誤っていることが原因で発生するエラーを減らすためです。
次のパラメータは、現在、排他的なキーワード引数です。
Client.send_message()
tts
Client.logs_from()
before
after
Client.edit_channel_permissions()
allow
deny
ドキュメントでは、関数シグネチャ内の \*,
の後に引数があるかどうかで、関数の引数が強制的なキーワード引数であるかを知ることができます。
クライアントの実行¶
以前のバージョンのdiscord.pyでは client.run()
は呼び出したメインスレッドをブロッキングするブロック付き呼び出しでした。v0.10.0でも未だブロック付き呼び出しですが、イベントループで処理を行います。ただし、それを行うためには認証情報を Client.run()
に渡す必要があります。
以前:
client.login('token')
client.run()
更新後:
client.run('token')
警告
以前の Client.run
同様、新しくなった関数も最後に呼び出す必要があります。これは関数がブロッキングを行うためです。 Client.run()
の後に何かを定義しても、この関数が終了するまで、それらの処理は行われません。
これはイベントループを抽象化するユーティリティ関数です。 実行呼び出しがブロックされ、コントロールから外れる必要はありません。実際に、イベントループを制御したい場合、この方法では非常に簡単です。
import discord
import asyncio
client = discord.Client()
@asyncio.coroutine
def main_task():
yield from client.login('token')
yield from client.connect()
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main_task())
except:
loop.run_until_complete(client.logout())
finally:
loop.close()