使用urllib向网站JSON文件写入数据遇TypeError报错求助
无法通过urllib向远程JSON文件写入内容的问题修复
问题场景
我正在开发一款聊天机器人,通过urllib的urlopen函数加载网站上的bot.json文件,但无法向该JSON文件写入内容。
我的代码
import random import json from urllib.request import urlopen url = "https://proj002webhostingserver.husseingaming1.repl.co/bot.json" web = urlopen(url) def random_string(question): random_list = [ "Please try writing something more descriptive. Can You Please Respond With The Answer", "Oh! It appears you wrote something I don't understand yet, Can You Please Respond With The Answer", "Do you mind trying to rephrase that? Can You Please Respond With The Answer", "I'm terribly sorry, I didn't quite catch that. Can You Please Respond With The Answer", "I can't answer that yet, please try asking something else. Can You Please Respond With The Answer" ] list_count = len(random_list) random_item = random.randrange(list_count) web = urlopen(url) response_data = load_json(web) print(random_list[random_item]) respinp = input("Type Your Response To That Question: ") reqwinp = list(input("Type Any Requierd Words Here(Leave empty if there are none)(use this format: [\"word1\", \"word 2\"] you can use more than 2 or less than 2): ")) new(question=question, response= respinp, required_words= reqwinp) def load_json(file): with urlopen(url) as bot_responses: print(f"Loaded \"{file}\" successfully!") return json.load(bot_responses) def new(question: str, response: str, required_words: None and str): """_summary_ Args: question (str): The question that you asked response (str): An answer to the question required_words (Noneandstr): any requierd words for this question(leave empty if there are no required words) """ data = load_json(web) data.append({ "response_type": "added", "user_input": [question], "bot_response": response, "required_words": [required_words] }) with urlopen(url, "w") as file: json.dumps(data, file) random_string("hi")
运行错误信息
Exception has occurred: TypeError POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str. File "/Users/hussein/Desktop/Chatbot_proj_Callback001_version1/random_responses.py", line 49, in new with urlopen(url, "w") as file: ^^^^^^^^^^^^^^^^^ File "/Users/hussein/Desktop/Chatbot_proj_Callback001_version1/random_responses.py", line 25, in random_string new(question=question, response= respinp, required_words= reqwinp) File "/Users/hussein/Desktop/Chatbot_proj_Callback001_version1/random_responses.py", line 51, in <module> random_string("hi") TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
问题分析与修复方案
核心问题拆解
urlopen用法错误:urlopen的第二个参数不是文件打开模式(如"w"),而是要发送的POST请求数据。传入"w"会被当成字符串类型的POST数据,不符合要求导致类型错误。- 远程文件写入逻辑错误:不能像操作本地文件那样直接"写入"远程JSON,需要发送合法的HTTP请求(PUT/POST/PATCH,取决于服务器支持),并正确编码数据、设置请求头。
- 其他次要问题:
load_json函数的参数file未被使用,逻辑冗余reqwinp用list(input(...))会把输入字符串拆成单个字符,应该用json.loads()解析列表格式输入new函数的参数类型标注错误,required_words: None and str不符合语法规范
修复后的代码
import random import json from urllib.request import Request, urlopen from typing import Optional, List url = "https://proj002webhostingserver.husseingaming1.repl.co/bot.json" def random_string(question): random_list = [ "请尝试描述得更详细一些,请给出对应的答案", "哦!看起来你写了一些我还不理解的内容,请给出对应的答案", "你介意重新表述一下吗?请给出对应的答案", "非常抱歉,我没太听清,请给出对应的答案", "我还无法回答这个问题,请尝试问点别的。请给出对应的答案" ] random_item = random.randrange(len(random_list)) print(random_list[random_item]) respinp = input("输入该问题的回复: ") reqwinp_input = input("输入所需关键词(无则留空,格式:[\"word1\", \"word2\"],可多可少): ") # 解析用户输入的列表格式,无输入则设为空列表 reqwinp = json.loads(reqwinp_input) if reqwinp_input.strip() else [] new(question=question, response=respinp, required_words=reqwinp) def load_json(): with urlopen(url) as bot_responses: print("加载bot.json成功!") return json.load(bot_responses) def new(question: str, response: str, required_words: Optional[List[str]]): data = load_json() data.append({ "response_type": "added", "user_input": [question], "bot_response": response, "required_words": required_words }) # 将JSON数据编码为字节格式 json_data = json.dumps(data).encode('utf-8') # 创建PUT请求(若服务器支持POST则改为POST) req = Request(url, data=json_data, method='PUT') # 设置请求头,告知服务器数据类型为JSON req.add_header('Content-Type', 'application/json') # 发送请求并处理响应 with urlopen(req) as response: print("数据写入成功!") print(response.read().decode('utf-8')) random_string("hi")
额外注意事项
- 确认服务器支持修改
bot.json的HTTP方法(PUT/POST/PATCH),若只允许特定方法需对应调整代码中的method参数 - 若服务器需要身份验证,需在请求头中添加对应的认证信息
- 处理用户输入时建议添加异常捕获,避免因输入格式错误导致程序崩溃
内容的提问来源于stack exchange,提问作者Nothing Around Us
相关产品推荐
相关产品推荐

