Мой код возвращает JSONDecodeError, но единственная вещь в файле - {} - PullRequest
0 голосов
/ 17 февраля 2020

Пожалуйста, прочтите до конца, прежде чем ответить.

Мой код загружает JSON из файла с именем reference.json. Затем он добавляет другой объект в файл, а затем сбрасывает его обратно в файл. Но когда это происходит, возвращается эта ошибка:

Ignoring exception in command import:
Traceback (most recent call last):
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\site-packages\discord\ext\commands\core.py", line 83, in wrapped
    ret = await coro(*args, **kwargs)
  File "C:\code\nexus-developments\workflow-discord-bot\cogs\import_test_suite.py", line 120, in attach_command
    self.dump_json(json_content, new_file, new_channel, message=message)
  File "C:\code\nexus-developments\workflow-discord-bot\cogs\import_test_suite.py", line 61, in dump_json
    reference_content = json.load(reference_file)
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\json\__init__.py", line 299, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\json\__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\json\decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\json\decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\site-packages\discord\ext\commands\bot.py", line 892, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\site-packages\discord\ext\commands\core.py", line 797, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Users\Joshua\Anaconda3\envs\workflow-discord-bot-env\lib\site-packages\discord\ext\commands\core.py", line 92, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: JSONDecodeError: Expecting value: line 1 column 1 (char 0)

JSON file:

{}

Фрагмент кода:

    def dump_json(self, json_content, new_file, channel, message=None):
        if new_file:
            reference_file = open("json/reference.json", "w+")

            reference_content = json.load(reference_file)

            reference_content[str(channel.name)] = {}
            reference_content[str(channel.name)]["guild_id"] = int(channel.guild.id)
            reference_content[str(channel.name)]["channel_id"] = int(channel.id)
            reference_content[str(channel.name)]["message_id"] = int(message.id)

            json.dump(reference_content, reference_file, indent=4)

        file = open(f"json/{channel.name}.json", "w")

        json.dump(json_content, file, indent=4)

Полный код:

from discord.ext import commands
from os import path
import utils
import discord
import json


class ImportTestSuite(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    async def get_json_content(self, ctx):
        attachments = ctx.message.attachments

        if len(attachments) == 0:
            embed = discord.Embed(description="You need to provide 1 JSON attachment",
                                  timestamp=ctx.message.created_at,
                                  colour=discord.colour.Colour.red())

            embed = utils.add_promotion_footer(embed)

            await ctx.send(embed=embed)

            return None

        attachment = attachments[0]

        if attachment.filename.split(".")[1] != "json":
            embed = discord.Embed(description="You must attach a `.json` file",
                                  timestamp=ctx.message.created_at,
                                  colour=discord.colour.Colour.red())

            embed = utils.add_promotion_footer(embed)

            await ctx.send(embed=embed)

            return None

        attachment_content = await attachment.read()

        try:
            json_content = json.loads(attachment_content)
        except json.JSONDecodeError:
            embed = discord.Embed(description="You must attach valid JSON.\nUse "
                                              "https://jsonformatter.curiousconcept.com/ or an alternative to"
                                              " validate JSON",
                                  timestamp=ctx.message.created_at,
                                  colour=discord.colour.Colour.red())

            embed = utils.add_promotion_footer(embed)

            await ctx.send(embed=embed)

            return None

        return json_content

    def dump_json(self, json_content, new_file, channel, message=None):
        if new_file:
            print(message)
            print(channel.id)
            reference_file = open("json/reference.json", "w+")

            reference_content = json.load(reference_file)

            reference_content[str(channel.name)] = {}
            reference_content[str(channel.name)]["guild_id"] = int(channel.guild.id)
            reference_content[str(channel.name)]["channel_id"] = int(channel.id)
            reference_content[str(channel.name)]["message_id"] = int(message.id)

            json.dump(reference_content, reference_file, indent=4)

        file = open(f"json/{channel.name}.json", "w")

        json.dump(json_content, file, indent=4)

    async def setup_new_channel(self, ctx, channel):
        new_channel = await channel.category.create_text_channel(channel.name,
                                                                 overwrites=channel.overwrites,
                                                                 position=channel.position,
                                                                 topic=channel.topic,
                                                                 nsfw=channel.is_nsfw())

        await channel.delete()

        embed = discord.Embed(description="React with ✅ to start the test",
                              timestamp=ctx.message.created_at,
                              colour=discord.colour.Colour.green())

        embed = utils.add_promotion_footer(embed)

        message = await new_channel.send(embed=embed)

        await message.add_reaction("✅")

        return message, new_channel

    def check_if_new_file(self, channel):
        new_file = False

        if not path.exists(f"json/{channel.name}.json"):
            new_file = True

        return new_file

    @commands.command(name="import")
    async def attach_command(self, ctx, channel: discord.TextChannel = None):
        if channel is None:
            channel = ctx.message.channel

        json_content = await self.get_json_content(ctx)

        if json_content is None:
            return

        new_file = self.check_if_new_file(channel)

        if new_file:
            message, new_channel = await self.setup_new_channel(ctx, channel)

            self.dump_json(json_content, new_file, new_channel, message=message)
        else:
            await ctx.message.delete()

            self.dump_json(json_content, new_file, channel)


def setup(bot):
    bot.add_cog(ImportTestSuite(bot))

Я пробовал разные режимы и проверял, правильные ли данные, все это хорошо.

Заранее спасибо

1 Ответ

0 голосов
/ 17 февраля 2020

Причина указана в этом другом сообщении SO: Смущен python режим файла "w +" . но не закрытие как дубликат, потому что это может быть неочевидно на первый взгляд.

Трассировка стека ошибок дает строку в вашем коде, которая вызывает ошибку:

File "C:\code\nexus-developments\workflow-discord-bot\cogs\import_test_suite.py", line 61, in dump_json
reference_content = json.load(reference_file)

Непосредственно перед этим мы можем find:

reference_file = open("json/reference.json", "w+")

Как объяснено в ссылочном посте, режим w+ усекает файл до 0 длины, а json не читает ваши инициализированные данные, но пустой файл и ничего не находит, начиная с char 0, отсюда и сообщение об ошибке.

...