Я создал бота для своего сервера Discord, который переходит к API Reddit для данного поддредита и публикует 10 лучших результатов за день в чате Discord на основе введенных вами подредитов.Он не учитывает собственные сообщения и действительно только публикует картинки и GIF-изображения.Команда Discord message будет выглядеть примерно так: =get funny awww news programming
, публикуя результаты для каждого subreddit по мере их получения из Reddit API (PRAW).Это работает без проблем.Я знаю, что способность бота поразить API и публиковать в разлад работает.
Я добавил еще одну команду =getshuffled
, которая помещает все результаты из подредактов в большой список, а затем перетасовывает их перед публикацией.Это работает очень хорошо с запросом до ~ 50 subreddits.
Вот что мне нужно, чтобы помочь:
Поскольку это может быть такой большой список результатов, более 1000 результатов из 100+ подредакторов, бот падает надействительно большие запросы.Исходя из того, какую помощь я получил от моего вопроса вчера , я понимаю, что происходит не так.Бот запускается, он общается с моим сервером Discord, и когда я передаю ему длинный запрос, он перестает слишком долго разговаривать с сервером, пока выполняется вызов API Reddit, и в случае сбоя соединения Discord.
Итак, что я думаю , что мне нужно сделать, - это создать подпроцесс для кода, который идет в Reddit API и извлекает результаты (что, я думаю, позволит диссонансному соединению работать), изатем передайте эти результаты НАЗАД боту, когда он закончит ....
Или ... это то, что Asyncio может обрабатывать самостоятельно ...
У меня естьтрудные времена с вызовом подпроцесса, как я и знал.
По сути, мне либо нужна помощь с этим обманом подпроцесса, либо мне нужно знать, являюсь ли я идиотом, и Asyncio справится со всем этим для меня,Я думаю, что это только один из тех примеров «я не знаю, чего я не знаю».
Итак, резюмируем: бот работал нормально с перемешанным меньшим количеством субреддитов.Он проходит через отправленные аргументы (которые являются subreddits), захватывает информацию для каждого поста, а затем перетасовывается перед публикацией ссылок на раздор.Проблема в том, что это большой набор подредакторов ~ 50+.Чтобы заставить его работать с большей суммой, мне нужно, чтобы вызов Reddit НЕ блокировал соединение с основным диссонансом, и именно поэтому я пытаюсь создать подпроцесс.
Версия Python 3.6 и Discord.py версия 0.16.12 Этот бот размещен и работает на PythonAnywhere
Код:
from redditBot_auth import reddit
import discord
import asyncio
from discord.ext.commands import Bot
#from discord.ext import commands
import platform
import subprocess
import ast
client = Bot(description="Pulls posts from Reddit", command_prefix="=", pm_help = False)
@client.event
async def on_ready():
return await client.change_presence(game=discord.Game(name='Getting The Dank Memes'))
def is_number(s):
try:
int(s)
return True
except:
pass
def show_title(s):
try:
if s == 'TITLES':
return True
except:
pass
async def main_loop(*args, shuffled=False):
print(type(args))
q=10
#This takes a integer value argument from the input string.
#It sets the number variable,
#Then deletes the number from the arguments list.
title = False
for item in args:
if is_number(item):
q = item
q = int(q)
if q > 15:
q=15
args = [x for x in args if not is_number(x)]
if show_title(item):
title = True
args = [x for x in args if not show_title(x)]
number_of_posts = q * len(args)
results=[]
TESTING = False #If this is turned to True, the subreddit of each post will be posted. Will use defined list of results
if shuffled == False: #If they don't want it shuffled
for item in args:
#get subreddit results
#post links into Discord as it gets them
#The code for this works
else: #if they do want it shuffled
output = subprocess.run(["python3.6", "get_reddit.py", "*args"])
results = ast.literal_eval(output.decode("ascii"))
# ^^ this is me trying to get the results back from the other process.
.Это мой файл get_reddit.py:
#THIS CODE WORKS, JUST NEED TO CALL THE FUNCTION AND RETURN RESULTS
#TO THE MAIN_LOOP FUNCTION
from redditBot_auth import reddit
import random
def is_number(s):
try:
int(s)
return True
except:
pass
def show_title(s):
try:
if s == 'TITLES':
return True
except:
pass
async def get_results(*args, shuffled=False):
q=10
#This takes a integer value argument from the input string.
#It sets the number variable,
#Then deletes the number from the arguments list.
title = False
for item in args:
if is_number(item):
q = item
q = int(q)
if q > 15:
q=15
args = [x for x in args if not is_number(x)]
if show_title(item):
title = True
args = [x for x in args if not show_title(x)]
results=[]
TESTING = False #If this is turned to True, the subreddit of each post will be posted. Will use defined list of results.
NoGrabResults = False
#This pulls the data and creates a list of links for the bot to post
if NoGrabResults == False:
for item in args:
try:
#get the posts
#put them in results list
except Exception as e:
#handle error
pass
try:
#print('____SHUFFLED___')
random.shuffle(results)
random.shuffle(results)
random.shuffle(results)
except:
#error stuff
print(results)
#I should be able to read that print statement for the results,
#and then use that in the main bot function to post the results.
.
@client.command()
async def get(*args, brief="say '=get' followed by a list of subreddits", description="To get the 10 Top posts from a subreddit, say '=get' followed by a list of subreddits:\n'=get funny news pubg'\n would get the top 10 posts for today for each subreddit and post to the chat."):
#sr = '+'.join(args)
await main_loop(*args)
#THIS POSTS THE POSTS RANDOMLY
@client.command()
async def getshuffled(*args, brief="say '=getshuffled' followed by a list of subreddits", description="Does the same thing as =get, but grabs ALL of the posts and shuffles them, before posting."):
await main_loop(*args, shuffled=True)
client.run('my ID')
ОБНОВЛЕНИЕ: Следуя совету, команда прошла через ThreadPoolExecutor, как показано:
async def main(*args, shuffled):
if shuffled==True:
with concurrent.futures.ThreadPoolExecutor() as pool:
results = await asyncio.AbstractEventLoop().run_in_executor(
executor=pool, func=await main_loop(*args, shuffled=True))
print('custom thread pool', results)
, но это все равно приводит к ошибкам при попытке сценарияпоговорить с Discord:
ERROR:asyncio:Task was destroyed but it is pending!
task: <Task pending coro=<Client._run_event() running at /home/GageBrk/.local/lib/python3.6/site-packages/discord/client.py:307> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f28acd8db28>()]>>
Event loop is closed
Destination must be Channel, PrivateChannel, User, or Object. Received NoneType
Destination must be Channel, PrivateChannel, User, or Object. Received NoneType
Destination must be Channel, PrivateChannel, User, or Object. Received NoneType
...
Он отправляет результаты правильно, но Discord все еще теряет связь.