どーもたかぽんです...!
先ほどDiscordを使っていい感じにbot作ってみよ〜っていうのを試していたのですが、一箇所結構つまづいたところがあったので、それについて書いていこうと思います。
発生したエラー
まず、筆者がつまづいたところなんですが...
簡単にいうとDiscordと接続を確立して、スラッシュコマンドを実装しようとした際、プログラムを動かそうとしてもうまく動かなかったんですね...
雑なイメージだと以下のようなコードがこけてしまっていました。
TOKEN = "DiscordBotToken"
client = discord.Bot()
client.run(TOKEN)
discordapp.comのホストへアクセスする際、certificate verify failedとなり、認証が失敗しているようでした。
ちょっと長くなってしまいますが...実際のエラーは以下になります。
taka@Taka discord % python3 command-bot.py
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/connector.py", line 980, in _wrap_create_connection
return await self._loop.create_connection(*args, **kwargs) # type: ignore[return-value] # noqa
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 1081, in create_connection
transport, protocol = await self._create_connection_transport(
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 1111, in _create_connection_transport
await waiter
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/sslproto.py", line 528, in data_received
ssldata, appdata = self._sslpipe.feed_ssldata(data)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/sslproto.py", line 188, in feed_ssldata
self._sslobj.do_handshake()
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 944, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/taka/Practice/python/discord/command-bot.py", line 27, in <module>
client.run(TOKEN)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/discord/client.py", line 717, in run
return future.result()
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/discord/client.py", line 696, in runner
await self.start(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/discord/client.py", line 659, in start
await self.login(token)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/discord/client.py", line 514, in login
data = await self.http.static_login(token.strip())
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/discord/http.py", line 406, in static_login
data = await self.request(Route("GET", "/users/@me"))
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/discord/http.py", line 280, in request
async with self.__session.request(
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/client.py", line 1141, in __aenter__
self._resp = await self._coro
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/client.py", line 536, in _request
conn = await self._connector.connect(
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/connector.py", line 540, in connect
proto = await self._create_connection(req, traces, timeout)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/connector.py", line 901, in _create_connection
_, proto = await self._create_direct_connection(req, traces, timeout)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/connector.py", line 1206, in _create_direct_connection
raise last_exc
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/connector.py", line 1175, in _create_direct_connection
transp, proto = await self._wrap_create_connection(
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/aiohttp/connector.py", line 982, in _wrap_create_connection
raise ClientConnectorCertificateError(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host discord.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')]
最初はコードが何か変なのか?と思い、いろんな方のdiscord bot導入周りの情報を見たけどやはり問題はなさそうでした。
エラーの原因と解決方法
さて、エラーの原因ですが...調べていくとこちらのgithubに行きつきました。
openSSL周りの知識があまりないので正確に理解できている自信はないのですが...
python3.6以降, (おそらくMacユーザーのみは)pythonのsslモジュールでは証明書が使用されない様でした。
実際に...
Macintosh HD > Application > Python 3.9
のフォルダ内を探してみると、ReadMe.rtfがあり、下記記載の文言が書かれていました。
// ReadMe.rtfから一部抜粋
This package will install Python 3.9.1 for macOS 10.9 or later for the following architecture(s): arm64, x86_64.
Certificate verification and OpenSSL
This package includes its own private copy of OpenSSL 1.1.1.
The trust certificates in system and user keychains managed by the
Keychain Access application and the security command line utility
are not used as defaults by the Python ssl module.
A sample command script is included in /Applications/Python 3.9 to install
a curated bundle of default root certificates from the third-party certifi package
(https://pypi.org/project/certifi/).
Double-click on Install Certificates to run it.
ここを見た感じ、Install Certificatesのファイルをダブルクリックして実行すれば一通り問題ない形に環境が構築されるっぽかったので、同じく"Python 3.9"ファイルにある、"Install Certificates.command"ファイルをダブルクリックすると...
コマンドラインが立ち上がって...
"プロセスが完了しました"と表示されました。
そして、再度先ほどのエラーになったコマンドを実行すると問題なく動作しました。
まとめ
今回はpythonで出会ったエラーについてでした...!
正直自分が書いたコード自体のエラーならまぁわかりやすいんですけど、よくわからないことが急に出るとやっぱり時間かかっちゃいますね...
解決につながった質問へのリンクも載せておきます...!
stack overflowに感謝感謝...