【问题标题】:ValueError: I/O operation on closed file. What's wrong with my code?ValueError:对已关闭文件的 I/O 操作。我的代码有什么问题?
【发布时间】:2021-11-29 17:40:41
【问题描述】:

我的代码有问题,我不知道如何解决。我发现了很多类似的问题,但没有一个能解决我的问题。我使用 Visual Studio Code 作为代码编辑器。这是我的代码:

import discord
import json

with open('config.json') as config_file:
    config = json.load(config_file)

with open('data.json', 'r+') as data_file:
    data = json.load(data_file)

client = discord.Client()

@client.event
async def on_ready():
    print("Logged in as " + str(client.user))

@client.event
async def on_message(msg):
    if msg.author == client.user: return

    if msg.content == '!gcsetup':
        server_json_content = {}
        server_json_content["channel"] = msg.channel.id
        webhook = await msg.channel.create_webhook(name="name")
        server_json_content["webhook"] = webhook.url
        data.append(server_json_content)
        data_file.seek(0)
        json.dump(data, data_file)

client.run(config["token"])

我认为错误在这里:

    if msg.content == '!gcsetup':
        server_json_content = {}
        server_json_content["channel"] = msg.channel.id
        webhook = await msg.channel.create_webhook(name="name")
        server_json_content["webhook"] = webhook.url
        data.append(server_json_content)
        data_file.seek(0)
        json.dump(data, data_file)

根据报错错误信息:

Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\client.py", line 343, in _run_event
    await coro(*args, **kwargs)
  File "E:\Dev\main.py", line 26, in on_message
    data_file.seek(0)
ValueError: I/O operation on closed file.

【问题讨论】:

  • data_file 变量在哪里定义。换句话说,你在哪里打开了一个文件并将其保存在 data_file 中?!
  • @Grasshopper with open('data.json', 'r+') as data_file
  • 用你自己的话来说,with open('data.json', 'r+') as data_file: 是什么意思?您认为该区块的末尾会发生什么?您认为使用with 语句而不是简单地正常调用open目的是什么?
  • 除了其他人解释的问题的直接答案之外,全局变量通常不受欢迎。它们可能会导致像这样的错误。如果您使用本地with 块打开on_message() 中的data.json 文件,那么您将完全避免该问题。

标签: python file


【解决方案1】:

当您使用with open()... 语句打开文件句柄时,您会在 with 块的末尾隐式关闭句柄。因此,当您调用 data_file.seek 时,您正试图对已关闭的文件执行 I/O 操作,如错误消息所示。

最简单的解决方案是在进行转储时重新打开文件进行写入。这也避免了寻找文件开头的需要,因为这将是您以写入模式打开时的默认行为。

    if msg.content == '!gcsetup':
        server_json_content = {}
        server_json_content["channel"] = msg.channel.id
        webhook = await msg.channel.create_webhook(name="name")
        server_json_content["webhook"] = webhook.url
        data.append(server_json_content)
        with open('data.json', 'w') as data_file:
            json.dump(data, data_file)

虽然您也可以不使用 with 块(因此永远不要关闭文件句柄),但最好不要为整个 discord 服务器保留大量打开的文件句柄

【讨论】:

    【解决方案2】:

    data_file 变量仅存在于with open('data.json', 'r+') as data_file: 块中,因此您不能在with 之外使用它。
    试着写

    data_file = open('data.json', 'r+')
    data = json.load(data_file)
    

    代替

    with open('data.json', 'r+') as data_file:
        data = json.load(data_file)
    

    【讨论】:

    • 那么配置变量是如何工作的呢?
    • 配置变量未在 with 块内声明。
    猜你喜欢
    • 2013-05-03
    • 2013-09-27
    • 2016-07-21
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 2016-08-26
    • 2016-06-13
    相关资源
    最近更新 更多