Python Requests报错:'function' object is not iterable - Discord机器人问题
解决IdleRPG Discord机器人整合后线程报错问题
问题描述
开发的IdleRPG Discord机器人,单个函数单独运行正常,但整合后触发TypeError: 'function' object is not iterable错误,三个线程均会出现该问题。
原代码
import time import datetime import threading import requests import json import getpass import os print() print('-----------------------------------------------------------------------------------------------------') print() user = getpass.getuser() path = (f'C:/Users/{user}/autoadventure') if os.path.exists(path) == True: pass else: os.mkdir(path) boosters = input('Do you have boosters enabled? Y/N ').upper() adv = int(input('Which adventure did you want to idle? ')) leng = adv * 3600 chng = input('Are you using a different channel than last use? Y/N: ').upper() if chng == 'Y': channelid = input('Input Channel ID for discord: ') f = open(f'C:/Users/{user}/autoadventure/channelid.txt', 'w+') f.write(f'{channelid}') f.close() else: f = open(f'C:/Users/{user}/autoadventure/channelid.txt', 'r+') channelid = f.read() f.close() auth = input('Has your authorization key changed? Y/N: ').upper() if auth == 'Y': f = open(f'C:/Users/{user}/autoadventure/authkey.txt', 'w+') authcode = input('Please enter your authorization key: ') f.write(f'{authcode}') f.close() else: f = open(f'C:/Users/{user}/autoadventure/authkey.txt', 'r+') authcode = f.read() f.close() if boosters == 'Y': leng = leng/2 convert = datetime.timedelta(seconds=leng) # payloads url = f'https://discord.com/api/v9/channels/{channelid}/messages' adventure = { 'content': f"<@424606447867789312> adventure {adv}" } steal = { 'content': f"<@424606447867789312> steal" } pray = { 'content': f"<@424606447867789312> pray" } status = { 'content': f"<@424606447867789312> status" } headers = { 'authorization': f'{authcode}' } def adventure(): global adv msg= [] counter = 0 while True: time.sleep(5) r = requests.post(url, headers=headers, data=adventure,) print(f'Adventure Started | Level {adv} | Length {convert}') time.sleep(leng) r = requests.post(url, headers=headers, data=status,) counter = counter+1 time.sleep(2) r2 = requests.get(url, headers=headers,) info = json.loads(r2.text) for value in info: msg.append(value['content']) check = msg[0] if check == (f'You reached a new level:'): adv = adv+1 print(f'You leveled up! advancing to adventure {adv}!') print(f'Adventure {adv} Complete!') print(f'You have completed {counter} adventure(s) this session!') def pray(): while True: time.sleep(10) r = requests.post(url, headers=headers, data=pray,) print(f'Pray attempted, will try again in 5 hours') time.sleep(18000) def steal(): while True: time.sleep(15) r = requests.post(url, headers=headers, data=steal,) print(f'Steal attempted, will try again in 1 hour') time.sleep(3600) if __name__ == "__main__": p1 = threading.Thread(target=adventure) p2 = threading.Thread(target=pray) p3 = threading.Thread(target=steal) p1.start() p2.start() p3.start()
报错信息
Exception in thread Thread-1 (adventure): Traceback (most recent call last): File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016, in _bootstrap_inner self.run() File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\threading.py", line 953, in run self._target(*self._args, **self._kwargs) File "c:\Users\ethan\Desktop\autoadventurenew.py", line 74, in adventure r = requests.post(url, headers=headers, data=adventure,) File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\api.py", line 115, in post return request("post", url, data=data, json=json, **kwargs) File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\api.py", line 59, in request return session.request(method=method, url=url, **kwargs) File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\sessions.py", line 589, in request resp = self.send(prep, **send_kwargs) File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\sessions.py", line 703, in send r = adapter.send(request, **kwargs) File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\adapters.py", line 486, in send resp = conn.urlopen( File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 703, in urlopen httplib_response = self._make_request( File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 396, in _make_request conn.request_chunked(method, url, **httplib_request_kw) File "C:\Users\ethan\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connection.py", line 265, in request_chunked for chunk in body: TypeError: 'function' object is not iterable
问题原因
你定义的payload字典和同名函数重名了:
- 先定义了字典
adventure,随后又定义了同名函数def adventure():,函数会覆盖之前的字典变量,导致在函数内调用requests.post(..., data=adventure)时,实际传入的是函数对象而非字典 - 同理
pray和steal也存在完全相同的问题,字典与函数同名导致变量被覆盖
解决方案
修改payload字典的名称,避免与函数名冲突,比如给字典加上_payload后缀:
修改后的代码片段(关键部分)
# payloads url = f'https://discord.com/api/v9/channels/{channelid}/messages' # 修改字典名称,避免与函数重名 adventure_payload = { 'content': f"<@424606447867789312> adventure {adv}" } steal_payload = { 'content': f"<@424606447867789312> steal" } pray_payload = { 'content': f"<@424606447867789312> pray" } status = { 'content': f"<@424606447867789312> status" } headers = { 'authorization': f'{authcode}' } def adventure(): global adv msg= [] counter = 0 while True: time.sleep(5) # 使用修改后的字典名称 r = requests.post(url, headers=headers, data=adventure_payload,) print(f'Adventure Started | Level {adv} | Length {convert}') time.sleep(leng) r = requests.post(url, headers=headers, data=status,) counter = counter+1 time.sleep(2) r2 = requests.get(url, headers=headers,) info = json.loads(r2.text) for value in info: msg.append(value['content']) check = msg[0] if check == (f'You reached a new level:'): adv = adv+1 print(f'You leveled up! advancing to adventure {adv}!') print(f'Adventure {adv} Complete!') print(f'You have completed {counter} adventure(s) this session!') def pray(): while True: time.sleep(10) # 使用修改后的字典名称 r = requests.post(url, headers=headers, data=pray_payload,) print(f'Pray attempted, will try again in 5 hours') time.sleep(18000) def steal(): while True: time.sleep(15) # 使用修改后的字典名称 r = requests.post(url, headers=headers, data=steal_payload,) print(f'Steal attempted, will try again in 1 hour') time.sleep(3600)
额外说明
单个函数运行时不会触发该问题,是因为单个函数不存在同名变量覆盖的情况;整合后函数定义会覆盖之前的字典,所以才会报错。后续代码中尽量保持变量名和函数名的唯一性,避免此类命名冲突问题。
内容的提问来源于stack exchange,提问作者Ethan Murphy
相关产品推荐
相关产品推荐

