长话短说,我是API和异步编程的新手。我正在尝试制作一个Discord机器人,该机器人将您的Steam平台状态发布到bot的状态显示中(至少现在是这样),但是在运行Discord_Bot.py时出现此错误。不知道它是什么意思,为什么,但是它令我感到担忧,因为该错误似乎是在Discord的一个文件中发现的(我没有写过)。
首先,我在运行Discord_Bot.py之后立即收到此错误:
Ignoring exception in on_ready
Traceback (most recent call last):
File "C:\Users\Mira\Anaconda3\lib\site-packages\discord\client.py", line 307, in _run_event
yield from getattr(self, event)(*args, **kwargs)
TypeError: on_ready() missing 1 required positional argument: 'self'
File "C:\Users\USER\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "C:\Users\USER\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/USER/Documents/GitHub/Discord_Steam_Interface/Discord_Bot.py", line 83, in <module>
b.run_the_bot()
File "C:/Users/USER/Documents/GitHub/Discord_Steam_Interface/Discord_Bot.py", line 75, in run_the_bot
self.client.run(self.__BOT_TOKEN)
File "C:\Users\USER\Anaconda3\lib\site-packages\discord\client.py", line 534, in run
self.loop.close()
File "C:\Users\USER\Anaconda3\lib\asyncio\selector_events.py", line 107, in close
raise RuntimeError("Cannot close a running event loop")
RuntimeError: Cannot close a running event loop
然后我应用了nest_asyncio补丁,可以在这里找到它: https://github.com/erdewit/nest_asyncio
这似乎解决了问题,因为在运行脚本后,我不再立即收到“ RuntimeError:无法关闭运行事件循环”错误。但是,我现在注意到,如果让它运行约5分钟,它会重新出现。此外,脚本运行后立即继续出现以下错误。我不知所措,需要帮助吗?
Ignoring exception in on_ready
Traceback (most recent call last):
File "C:\Users\USER\Anaconda3\lib\site-packages\discord\client.py", line 307, in _run_event
yield from getattr(self, event)(*args, **kwargs)
TypeError: on_ready() missing 1 required positional argument: 'self'
import time
import win32gui
import psutil
import subprocess
import discord
import asyncio
import get_steam_info
import nest_asyncio
# Applies a patch which allows asyncio's event loop to be nested.
nest_asyncio.apply()
class Bot_handler():
# Define the Client object for this session.
client = discord.Client()
def __init__(self, program_name, steam_id, api_key, bot_token):
self.program_name = program_name
self.process = self.program_name + '.exe'
self.__program_running = self.get_program_running(self.process)
self.__STEAM_ID = STEAM_ID
self.__API_KEY = API_KEY
self.__BOT_TOKEN = BOT_TOKEN
def get_program_running(self, process_str):
'''Determine whether the specified process_str is running.'''
if process_str in (process.name() for process in psutil.process_iter()):
self.__program_running = True
print(self.program_name,"is currently running.")
else:
self.__program_running = False
print(self.program_name,"is not currently running.")
return self.__program_running
@client.event
async def on_ready(self):
'''Called automatically when client is done preparing data from Discord.
Schedules coroutine on_ready using Task client.loop.create_task.'''
self.__client.loop.create_task(self.status_task())
print('Logged in as')
print(self.__client.user.name)
print(self.__client.user.id)
print('------')
async def status_task(self):
while True:
if self.__program_running:
self.__player_info = get_steam_info.get_player_info(self.__API_KEY, self.__STEAM_ID)
self.__player_status = get_steam_info.get_player_status(self.__player_info)
self.__ingame = get_steam_info.get_ingame_name(self.__player_info)
if self.__ingame:
await self.__client.change_presence(status = discord.Status.online, game = discord.Game(name = str(self.__ingame)), afk=False)
await asyncio.sleep(3)
else:
await self.__client.change_presence(status = discord.Status.dnd, game = discord.Game(name = 'nothing at the moment'))
await asyncio.sleep(3)
else:
self.get_active_window()
def get_active_window(self):
'''Return the title of the active window as a string.'''
self.__active_window = win32gui.GetWindowText(win32gui.GetForegroundWindow())
return self.__active_window
def run_the_bot(self):
# Activates the bot.
self.client.run(self.__BOT_TOKEN)
PROGRAM_NAME = 'Steam'
# Real values are present in the code
STEAM_ID = 'ZZZZZZZZZ'
API_KEY = 'XXXXXXXX'
BOT_TOKEN = 'YYYYYYYYYY'
b = Bot_handler(PROGRAM_NAME, STEAM_ID, API_KEY, BOT_TOKEN)
b.run_the_bot()
import requests
class Info_handler():
'''Keep track of a player's information in real time.'''
def __init__(self, steam_ID, API_key):
self.__steam_ID = steam_ID
self.__API_key = API_key
self.__API_url = 'https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=' \
+ self.__API_key +'&steamids=' + self.__steam_ID
self.statuslist = {0: 'offline', 1: 'online', 3: 'dnd', 4: 'idle', 5: 'idle', 6: 'online', 7: 'online'}
# call status
# profile_url = 'https://steamcommunity.com/profiles/' + steam_ID
self.__player_info = self.get_player_info()
self.__player_status = self.get_player_status(self.__player_info)
def get_player_info(self):
'''Returns a dict containing Steam information for one player using the
Steam API. Requires the desired player's user ID and a valid API key.'''
self.response = requests.get(self.__API_url)
if self.response.status_code != 200:
raise Exception('Request unsuccessful; returned code ' + str(self.response.status_code) \
+ ': ' + str(requests.status_codes._codes[self.response.status_code][0]))
else:
print('Success! API responded to call.')
self.__player_info = self.response.json()['response']['players'][0]
return self.__player_info
def get_player_status(self, player_info_dict):
'''Returns the player's Steam status as a Discord status type.
STEAM STATUS | STEAM STATE | DISCORD STATUS
'Offline' | 0 | 'Offline'
'Online' | 1 | 'Online'
'Busy' | 2 | 'dnd'
'Away' | 3 | 'Idle'
'Snooze' | 4 | 'Idle'
'Looking to trade' | 5 | 'Online'
'Looking to play' | 6 | 'Online'
'''
self.__steam_state = player_info_dict['personastate']
self.__player_status = self.statuslist[self.__steam_state]
return self.__player_status
# Is it better to use 'self.__steam_state' since when this variable will never
# called outside the function? Or shall I use simply 'steam_state?'
def get_ingame_name(self, player_info_dict):
'''Returns the name of the Steam game player is playing.
If player is logged into Steam, but not currently playing anything,
return False.'''
self.__player_name = player_info_dict['personaname']
try:
self.__game = player_info_dict['gameextrainfo']
print('Player ',self.__player_name,' is playing ',self.__game,'.',sep='')
return self.__game
except KeyError:
print('Player',self.__player_name,'is not currently in a game.')
return False
def get_player_name(self):
return self.__player_name
steam_ID = 'ZZZZZZZZZ'
API_key = 'XXXXXXXX'
instance = Info_handler(steam_ID, API_key)
info = instance.get_player_info()
print(info)
status = instance.get_player_status(info)
print(status)
game = instance.get_ingame_name(info)
print(game)