长话短说,我是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",**kwargs)
TypeError: on_ready() missing 1 required positional argument: 'self'
这是Discord_Bot.py :(我的文件)
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()
get_steam_info.py(我的文件)
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','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)