별도의 스레드에서 run_coroutine_threadsafe 실행
Oct 15 2020
나는 끊임없이 계속 실행되는 스크립트가 있습니다 (파일의 변경 사항을 확인합니다). 이상한 파일이 만들어 질 때마다 Discord 메시지를 보내야합니다.
- 문제는 이벤트 감시 기능 (
def run(self):아래)이 하위 클래스에서 왔기 때문에으로 변경할 수 없다는 것async def run(self):입니다. 따라서 사용할 수 없습니다await channel.send() - 이에 대한 내 해결책은
run_coroutine_threadsafe여기에 설명 된 대로 사용하는 것입니다.https://stackoverflow.com/a/53726266/9283107. 잘 작동합니다! 그러나 문제는 메시지가 대기열에 들어가고이 스크립트가 완료 될 때까지 전송되지 않는다는 것입니다 (제 경우에는 절대로 없음). 메시지 보내기 기능이이 스크립트가있는 스레드에 넣어 진다고 가정합니다. 따라서 스레드가 해당 기능에 도달하지 않습니까?
아마도 우리는 run_coroutine_threadsafe별도의 스레드 또는 무언가에 던질 수 있습니까? 이것은 여전히 내 하위 클래스 문제를 보여주는 가장 최소한의 예제입니다.
import discord
import os
import asyncio
import time
# CHANNEL_ID = 7659170174????????
client = discord.Client()
channel = None
class Example():
# Imagine this run comes from a subclass, so you can't add sync to it!
def run(self):
# await channel.send('Test') # We can't do this because of the above comment
asyncio.run_coroutine_threadsafe(channel.send('Test'), _loop)
print('Message sent')
@client.event
async def on_ready():
print('Discord ready')
global channel
channel = client.get_channel(CHANNEL_ID)
for i in range(2):
Example().run()
time.sleep(3)
print('Discord messages should appear by now. Sleeping for 20s to give it time (technically this would be infinite)')
time.sleep(20)
print('Script done. Now they only get sent for some reason')
_loop = asyncio.get_event_loop()
client.run('Your secret token')
답변
2 user4815162342 Oct 15 2020 at 11:05
당신과 같은 코드를 차단 호출 할 수 없습니다 있다는 것을 우선, 참고 time.sleep()에서 async def. 차단 함수를 시작하고 asyncio와 통신하도록하려면 다음 on_ready과 같이 최상위 수준 에서 또는 최상위 수준에서 백그라운드 스레드를 생성 할 수 있습니다 .
# checker_function is the function that blocks and that
# will invoke Example.run() in a loop.
threading.Thread(
target=checker_function,
args=(asyncio.get_event_loop(), channel)
).start()
메인 스레드는 asyncio 이벤트 루프를 실행하고 백그라운드 스레드는 asyncio.run_coroutine_threadsafe()asyncio 및 discord와 통신하는 데 사용하여 파일을 확인합니다 .
링크 된 답변 아래의 주석에서 지적했듯이 asyncio.run_coroutine_threadsafe여러 스레드가 실행 중이라고 가정합니다 (따라서 "스레드 안전").이 중 하나는 이벤트 루프를 실행합니다. 이를 구현할 때까지 모든 사용 시도 asyncio.run_coroutine_threadsafe는 실패합니다.
2 Frank Oct 15 2020 at 10:59
다음 user4815162342질문에 대한 의견을, 나는 완벽하게 작동하는이 함께했다!
import discord
import os
import asyncio
import time
import threading
CHANNEL_ID = 7659170174????????
client = discord.Client()
channel = None
class Example():
# Imagine this run comes from a subclass, so you can't add sync to it!
def run(self):
# await channel.send('Test') # We can't do this because of the above comment
asyncio.run_coroutine_threadsafe(channel.send('Tester'), _loop)
print('Message sent')
def start_code():
for i in range(2):
Example().run()
time.sleep(20)
@client.event
async def on_ready():
print('Discord ready')
global channel
channel = client.get_channel(CHANNEL_ID)
threading.Thread(target=start_code).start()
_loop = asyncio.get_event_loop()
client.run('Your secret token')