discord.py
| |
최신 버전
| 1.6
|
필요 파이썬 버전
| 3.5.3 이상 3.9 미만
|
1. 개요
discord.py는 파이썬용 디스코드 봇 API이다. 개발 진입장벽이 낮은 discord.py를 입문으로서 많이 선택한다. 하지만 다른 언어에 비해 상대적으로 쉽다는 것이지 기본적인 파이썬 사용 방법을 모른다면 아무것도 할 수 없으므로 꼭 기초적인 문법을 익히고 공부하자.
2. 제작 시 유의 및 주의해야할 점
2.1. 제작 전
당연하지만 먼저 Python을 설치해야 한다. http://python.org에서 본인의 OS에 맞게 설치하자. 편집기는 IDLE이라는 프로그램이 알아서 깔리니 걱정하지 않아도 된다. [1]
파이썬 버전은 3.5.3 이상을 사용해야하며, 개발하기 전 파이썬 버전은 3.6 이상을 사용하는 것을 추천한다. 이전 python 2에서 지원하던 포맷팅 방식인 %-formatting와 str.format() 방식 역시 python3에서 사용이 가능하지만, 이들의 문제점은 입력할 값이 많아질 수록 매우 길어지며 지저분해 보이며 잦은 실수를 할 수 있다는 점이다.
아래 예시 말고도 다양한 다른 방법으로 활용이 가능하지만 기본적인 활용법을 보자.
공통적 변수:
예시(%-formatting):
예시(str.format()):
3.6 이상을 추천하는 이유는 3.6 이상부턴 f-string를 지원하기 때문이다.
예시(f-string):
볼 수 있듯 매우 깔끔하다.
파이썬 버전을 맞추었다면, 이번엔 discord.py의 버전을 맞출 차례다. 작성 시점 기준 discord.py는 1.3.3이 최신 버전이지만, 1.0.0이 업데이트된 19년 4월경 전까지는 17년 10월경에 업데이트된 0.16.12 버전을 대체로 사용했다. 프로그래밍에 익숙치않은 입문 및 초보자는 기본 지식을 얻기 위해 한국어로 작성된 discord.py 관련 자료들을 인터넷에서 찾아 읽을 수 있는데, 인터넷에 한국어로 작성된 discord.py 글들은 0.16.x 버전이 대부분이다. 이게 왜 유의해야 할 점이냐면, 0.16.x 버전과 1.0.0 이상의 버전은 상당 부분 호환이 안되어 0.16.x로 작성된 코드들은 1.0.0 이상에서 구동이 어렵다. 이로인해 만약 1.0.0 미만으로 작성된 글들을 참고하여 프로그래밍을 하고 싶다면, pip를 이용해 pip install discord.py==0.16.12[2]를 입력하면 == 뒤 버전으로 다운된다. 만약 본인이 영문 등으로 작성된 해외 글들을 찾아 읽을 수 있거나, 프로그래밍에 기본적인 지식이 있다면 1.0.0 이상을 사용하는 것을 추천한다.[3]
discord.py 비공식 한국어 문서가 생겼다.
바로가기
파이썬 버전은 3.5.3 이상을 사용해야하며, 개발하기 전 파이썬 버전은 3.6 이상을 사용하는 것을 추천한다. 이전 python 2에서 지원하던 포맷팅 방식인 %-formatting와 str.format() 방식 역시 python3에서 사용이 가능하지만, 이들의 문제점은 입력할 값이 많아질 수록 매우 길어지며 지저분해 보이며 잦은 실수를 할 수 있다는 점이다.
아래 예시 말고도 다양한 다른 방법으로 활용이 가능하지만 기본적인 활용법을 보자.
공통적 변수:
discord_py="discord.py"
discord="discord"
api="API"
namuwiki="나무위키"
예시(%-formatting):
>>> print("%s는 %s의 %s입니다. %s 문서는 %s에서 만들어졌습니다.)" % (discord_py, discord, api, discord_py, namuwiki)
'discord.py는 discord의 API입니다. discord.py 문서는 나무위키에서 만들어졌습니다.'
예시(str.format()):
>>> print("{}는 {}의 {}입니다. {} 문서는 {}에서 만들어졌습니다.)".format(discord_py, discord, api, discord_py, namuwiki)
'discord.py는 discord의 API입니다. discord.py 문서는 나무위키에서 만들어졌습니다.'
3.6 이상을 추천하는 이유는 3.6 이상부턴 f-string를 지원하기 때문이다.
예시(f-string):
>>> print(f"{discord_py}는 {discord}의 {api}입니다. {discord_py} 문서는 {namuwiki}에서 만들어졌습니다.")
'discord.py는 discord의 API입니다. discord.py 문서는 나무위키에서 만들어졌습니다.'
볼 수 있듯 매우 깔끔하다.
파이썬 버전을 맞추었다면, 이번엔 discord.py의 버전을 맞출 차례다. 작성 시점 기준 discord.py는 1.3.3이 최신 버전이지만, 1.0.0이 업데이트된 19년 4월경 전까지는 17년 10월경에 업데이트된 0.16.12 버전을 대체로 사용했다. 프로그래밍에 익숙치않은 입문 및 초보자는 기본 지식을 얻기 위해 한국어로 작성된 discord.py 관련 자료들을 인터넷에서 찾아 읽을 수 있는데, 인터넷에 한국어로 작성된 discord.py 글들은 0.16.x 버전이 대부분이다. 이게 왜 유의해야 할 점이냐면, 0.16.x 버전과 1.0.0 이상의 버전은 상당 부분 호환이 안되어 0.16.x로 작성된 코드들은 1.0.0 이상에서 구동이 어렵다. 이로인해 만약 1.0.0 미만으로 작성된 글들을 참고하여 프로그래밍을 하고 싶다면, pip를 이용해 pip install discord.py==0.16.12[2]를 입력하면 == 뒤 버전으로 다운된다. 만약 본인이 영문 등으로 작성된 해외 글들을 찾아 읽을 수 있거나, 프로그래밍에 기본적인 지식이 있다면 1.0.0 이상을 사용하는 것을 추천한다.[3]
discord.py 비공식 한국어 문서가 생겼다.
바로가기
2.2. discord와 discord.ext
위에 적혀있듯, 국내 자료들에선 대부분 1.0.0 미만을 사용하고 있다. discord.ext는 1.0.0에 추가된 함수들 폴더로, 1.0.0 미만엔 존재하지 않는다. 그래서 한국 자료 다수에선 구버전 방식인 discord.Client()를 사용하고 있지만 해외엔 ext 안에 있는 새로운 방식인 bot으로 작성된 봇의 자료들이 작성되어가고있으며, 이미 작성되어 있다.
Client() 예제:
이러한 방식은 코드량이 많아질 수록 지저분해지고 세분 및 체계화가 어렵다. 이러한 점을 해결하기 위해 추가된게 discord.ext 폴더 내에 있는 discord.ext.commands.Bot 객체 방식이다.
github에 소개 되어있는 commands.Bot 예제:
API에 대해 이해도가 조금 쌓여있는 상태라면 commands.Bot 방식이 훨씬 체계적이며 깔끔하고 유연하며, 쉽다는 것을 알 수 있다. 또한 cooldown, has_permission 등의 데코레이터가 만들어져 있어 굳이 다른 코드를 넣지 않아도 된다. 위에서 번역기를 사용해서라도 해외 자료를 참고하라는 이유가 이 때문이다. 영문이라 읽는데 어려움을 겪을진 몰라도, 프로그래밍에 있어선 훨씬 정갈하고 쉽다. 그러기에 이미 해외에선 commands.Bot 방식을 많이 사용하고 있다. 그렇다면 discord.ext만 import하면 되냐면, 그것도 아닌 게 기존의 discord 기본 모듈에 있는 discord.Embed, discord.Role 클래스 같은 것 들도 사용하기 위해 둘 다 모듈로 가져와야 한다. 이는 후술될 예제에서 참고하자.
Client() 예제:
import discord
client = discord.Client()
@client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
@client.event
async def on_message(message):
if message.content.startswith('!ping'):
await message.channel.send('pong')
client.run('token')
이러한 방식은 코드량이 많아질 수록 지저분해지고 세분 및 체계화가 어렵다. 이러한 점을 해결하기 위해 추가된게 discord.ext 폴더 내에 있는 discord.ext.commands.Bot 객체 방식이다.
github에 소개 되어있는 commands.Bot 예제:
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
@bot.event
async def on_ready():
print('Logged in as')
print(bot.user.name)
print(bot.user.id)
print('------')
@bot.command()
async def ping(ctx):
await ctx.send('pong')
bot.run('token')
API에 대해 이해도가 조금 쌓여있는 상태라면 commands.Bot 방식이 훨씬 체계적이며 깔끔하고 유연하며, 쉽다는 것을 알 수 있다. 또한 cooldown, has_permission 등의 데코레이터가 만들어져 있어 굳이 다른 코드를 넣지 않아도 된다. 위에서 번역기를 사용해서라도 해외 자료를 참고하라는 이유가 이 때문이다. 영문이라 읽는데 어려움을 겪을진 몰라도, 프로그래밍에 있어선 훨씬 정갈하고 쉽다. 그러기에 이미 해외에선 commands.Bot 방식을 많이 사용하고 있다. 그렇다면 discord.ext만 import하면 되냐면, 그것도 아닌 게 기존의 discord 기본 모듈에 있는 discord.Embed, discord.Role 클래스 같은 것 들도 사용하기 위해 둘 다 모듈로 가져와야 한다. 이는 후술될 예제에서 참고하자.
2.2.1. 1.0.0 버전 미만과 이상과의 명령어 호환
만약 1.0.0 버전 미만을 사용하다 1.0.0 이상의 버전으로 교체하여 구동에서 호환 문제가 발생하는 함수들을 모두 해결했지만, 새로 작성된 bot.command의 명령어 반응에 있어 문제를 겪을 수 있다. 이는 1.0.0 미만에서 사용하던 on_message 방식의 문제인데, on_message 방식은 계속해서 반복하며 입력되는 메세지에서 키워드를 검출해내는 방식이다. 계속해서 반복한다는 점 때문에 bot.commands가 프로세스되지 않는다. 그렇기에 이 상태론 둘을 함께 사용이 불가능하다. 하지만 on_message 아래 어느곳에든 @bot.command를 사용하는 경우에는 await bot.process_commands(message) 또는 @client.command를 사용하는 경우에는 await client.process_commands(message)를 입력해두면 둘을 함께 사용이 가능하다.
2.3. 개발 중 및 유지
만약 정상적으로 작동했던 봇이 어느날 정상 작동이 되지 않는다면, discord.py의 버전을 체크해봐야한다. 업데이트되어 호환이 안되거나 구버전 및 상위 버전 함수를 사용해 오류가 날 가능성도 있다. 해결법은 위에서 있듯 ==를 통해 전에 사용하던 버전으로 재설치하면 된다.
이건 discord.py를 사용하는 봇 외에 모두 공통으로 적용되는 점이지만, 봇 토큰을 타인에게 절대 노출하면 안된다. 봇 토큰은 각 봇들의 신분증처럼 연결중인 봇이 어떤 봇인가 증명하는 수단이다. 노출되어 문제가 발생한다면 누군가 내 껍데기를 뒤집어 씌고 본인인 것 마냥 행세하는 격의 일이 벌어질 수 있다.
봇의 사용인원이나 규모가 조금 커지면 테스트용 봇을 만들어 테스트 후 옮겨서 업데이트를 하는 방식을 추천한다. 어떠한 이유로 코드가 유실되거나 문제가 생길 수 있기 때문이다. 그 외에도 유지보수의 수월함을 위해 extension 기능을 이용해 세분화 시키고 코드 파일들을 불러들이면 좋다.
discord.py 1.3.3에 이슈가 생겼다. Discord API가 변경됨에 따라 타입 에러가 발생한다. 해결법은 이렇다.
이건 discord.py를 사용하는 봇 외에 모두 공통으로 적용되는 점이지만, 봇 토큰을 타인에게 절대 노출하면 안된다. 봇 토큰은 각 봇들의 신분증처럼 연결중인 봇이 어떤 봇인가 증명하는 수단이다. 노출되어 문제가 발생한다면 누군가 내 껍데기를 뒤집어 씌고 본인인 것 마냥 행세하는 격의 일이 벌어질 수 있다.
봇의 사용인원이나 규모가 조금 커지면 테스트용 봇을 만들어 테스트 후 옮겨서 업데이트를 하는 방식을 추천한다. 어떠한 이유로 코드가 유실되거나 문제가 생길 수 있기 때문이다. 그 외에도 유지보수의 수월함을 위해 extension 기능을 이용해 세분화 시키고 코드 파일들을 불러들이면 좋다.
discord.py 1.3.3에 이슈가 생겼다. Discord API가 변경됨에 따라 타입 에러가 발생한다. 해결법은 이렇다.
pip install --upgrade discord.py
python 3.9 업데이트 관련해서 문제가 생겼다.
pip install discord.py
명령어를 입력하면, Falied to build yarl multidict라는 문구와 함께 다운로드에 실패한다.https://github.com/Rapptz/discord.py/discussions/5898
이는 파이썬이 3.9 버전으로 업데이트 하면서 생긴 wheels 제공 관련 문제로, [4] 라이브러리 제작자가 이에 맞게 업데이트할 때까지 기다리거나, python 3.8.6 버전으로 다운그레이드하면 해결된다.
discord.py 설치시, 콘솔이 오류를 뿜어낼 때가 있다. 어느 정도까지는 잘 되다가 마는데, MS visual c++ build tools 2015 이상을 설치하면 대부분 된다. 위의 오류가 아마 같은 것일 듯. 자세한 내용은 아직...
이는 파이썬이 3.9 버전으로 업데이트 하면서 생긴 wheels 제공 관련 문제로, [4] 라이브러리 제작자가 이에 맞게 업데이트할 때까지 기다리거나, python 3.8.6 버전으로 다운그레이드하면 해결된다.
discord.py 설치시, 콘솔이 오류를 뿜어낼 때가 있다. 어느 정도까지는 잘 되다가 마는데, MS visual c++ build tools 2015 이상을 설치하면 대부분 된다. 위의 오류가 아마 같은 것일 듯. 자세한 내용은 아직...
3. 업데이트
discord.py는 깃허브에서 개발되고 있으며, 릴리즈가 나올 때마다 pypl에 업데이트가 되는 식이다. 이에 따라 아직 정식 릴리즈에 추가 되지 않은 기능들을 미리 사용하려면 깃허브에서 git을 이용해 업데이트를 해야 한다.
업데이트 방법:
업데이트 방법:
pip install -U git+https://github.com/Rapptz/discord.py.git
깃허브에 올라온 모듈을 그대로 업데이트시키는 명령이므로 (정식 릴리즈 판에 비해) 버그, 오류가 있을 수 있다.
그러나 아직 정식 버전에 추가되지 않은 (예를 들어 message.reply) 기능들을 미리 사용해 볼 수 있다.
그러나 아직 정식 버전에 추가되지 않은 (예를 들어 message.reply) 기능들을 미리 사용해 볼 수 있다.
4. 프로그래밍 예제
이미 인터넷에 한국어 문서가 있는 구버전 discord.Client()보단 discord.ext.comamnds.Bot 클래스를 주로 이용해서 작성해주세요. 입문용으로 많이 선호하는만큼 discord.py와 관련된 함수에 설명 주석을 넣어주면 좋습니다. 아래 예제는 예제인만큼 아래 방식뿐만아닌 다른 방식으로도 구현이 가능할 수 있습니다. 만약 다른 방식이지만 의미가 미미한 수준이면 추가는 삼가 주세요. 파이썬 자체에 대한 설명은 Python 또는 해외 자료를 통해 참고해주세요.
4.1. discord.ext.commands
4.1.1. 기본 대화 및 출력
discord.Client() 객체의 메서드는 모두 사용이 가능한데, 이는 discord.Client() 객체를 상속했기 때문이다.
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
'''
봇이 반응을 해야하는 명령어인지 구분하기 위해 메세지 앞에 붙이는 접두사(prefix)를 설정합니다. 현재 !로
설정되어있습니다. 이곳을 변경시 해당 문자로 명령어를 시작해야합니다. ext에선 discord.Client() 클래스 처럼
str.startswith 메서드를 사용할 필요가 없습니다.
'''
@bot.event
async def on_ready():
print('Logged in as')
print(bot.user.name) # 토큰으로 로그인 된 bot 객체에서 discord.User 클래스를 가져온 뒤 name 프로퍼티를 출력
print(bot.user.id) # 위와 같은 클래스에서 id 프로퍼티 출력
print('------')
@bot.command()
async def ping(ctx):
await ctx.send(f'pong! {round(round(bot.latency, 4)*1000)}ms') # 봇의 핑을 pong! 이라는 메세지와 함께 전송한다. f-string은 위에 서술되어 있다시피 버전 3.6 이상부터 사용 가능하다.
@bot.command(name="1234")
async def _1234(ctx):
await ctx.send("5678")
#파이썬 문법에 따라 함수를 만들 때에는 첫글자에는 숫자를 넣을 수 없는데, 숫자를 사용하고싶다면 함수 이름 자리는 다른 아무것으로 대체하고 괄호 안에 name=""을 사용하여 명령어를 수행할 수 있다.
bot.run('token')
4.2. discord.Client()
4.2.1. 기본 대화 및 출력
import discord
client = discord.Client()
@client.event
async def on_ready(): # 봇이 실행 준비가 되었을 때 행동할 것
print('Logged in as')
print(client.user.name) # 클라이언트의 유저 이름을 출력합니다.
print(client.user.id) # 클라이언트의 유저 고유 ID를 출력합니다.
# 고유 ID는 모든 유저 및 봇이 가지고있는 숫자만으로 이루어진 ID입니다.
print('------')
@client.event
async def on_message(message): # 입력되는 메세지에서 찾기
if message.content.startswith('!ping'): # 만약 메세지가 '!ping'으로 시작된다면
await message.channel.send('pong') # 클라이언트는 메세지가 올라온 채널에 'pong'을 보냅니다.
if message.content.startswith('!pong'):
await message.channel.send('ping!')
'''
on_message에서 또다른 명령어 추가를 위해
if message.content.startswith를 추가해야하는데, elif가 아닌 개별 if를 사용하는 것을 추천합니다.
'''
client.run('token')
만약 봇의 메세지는 반응하고싶지 않다면, on_message 최상단에
if message.author == client.user: # 만약 메시지를 보낸 사람과 봇이 서로 같을 때
return
if message.author.bot: # discord.User.bot 프로퍼티가 참일 때
return
을 하면 반응하지 않는다.[5]
아래는 client를 사용할때 더 깔끔하고 간단하게 쓸 수 있는 방법
import discord
client = discord.Client()
prefix ='!' # 접두사
@client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
@client.event
async def on_message(message):
cmd = message.content.split(prefix)[1].split()[0] # 명령어를 저장한다
args = message.content.split(cmd)[1][1:].split() # 공백을 기준으로 args를 저장한다
if cmd == 'ping': # message.content.startswith('!ping') 이랑 똑같은 역할을 한다
await message.channel.send('ping!')
client.run('token')
5. discord.Client()의 prefix
기존 discord.Client() 자체에선 Prefix(접두사)를 지원하지 않는다.
그러므로 다음과 같은 변수를 이용해야 한다.
그러므로 다음과 같은 변수를 이용해야 한다.
import discord
client = discord.Client()
prefix = "!" # 접두사 설정하기
@client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
@client.event
async def on_message(message):
if message.content.startswith(f'{prefix}ping'):
await message.channel.send('pong')
client.run('token')
[1] 다만 개발 규모가 커지면 PyCharm이나 Visual Studio Code 등 전용 IDE를 사용하는 것이 좋다.[2] pip 환경 변수가 설정되어있지 않다면 py -3 -m pip install -U discord.py==0.16.12[3] 관련 지식이 없어도 아래에 후술될 이유 때문에서라도 번역기를 사용해서라도 1.0.0 이상을 사용하는 것을 추천한다.[4] 의존성 라이브러리인 aiohttp, yarl, multidict가 문제가 되고 있다.[5] 파이썬은 항상 위에서 아래로 한줄씩 구동된다는 점을 알아야 한다. 인터프리터 언어의 특징으로, 만약 저 코드가 명령어 아래에 있다면 먼저 실행되지 않아 소용이 없다.