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_closedon_socket_receiveon_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を介して公開された一部リストが、シーケンスではなくイテラブルに変更されたことを意味します。つまるところ、現在、特定の属性はイテラブルのみをサポートしており、シーケンスを扱うことができないことを意味しています。

影響を受ける属性は以下のとおりです。

以前は有効であったが、現在は無効である操作の例。

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のプロパティに変更されました。

以下はプロパティに変更された関数です。

変更前

変更後

User.avatar_url()

User.avatar_url

User.mention()

User.mention

Channel.mention()

Channel.mention

Channel.is_default_channel()

Channel.is_default

Role.is_everyone()

Role.is_everyone

Server.get_default_role()

Server.default_role

Server.icon_url()

Server.icon_url

Server.get_default_channel()

Server.default_channel

Message.get_raw_mentions()

Message.raw_mentions

Message.get_raw_channel_mentions()

Message.raw_channel_mentions

メンバー管理

BANやキックを含む関数が追加されました。

変更前

変更後

Client.ban(server, user)

Client.ban(member)

Client.kick(server, user)

Client.kick(member)

関数の改名

いくつかの関数名が変更されました。

変更前

変更後

Client.set_channel_permissions

Client.edit_channel_permissions()

すべての Permissions 関連の属性の名称が変更され、 接頭詞であった can_ が削除されました。例を挙げると can_manage_messagesmanage_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()