python 无法pickle< class>:模块导入失败

kdfy810k  于 2022-12-21  发布在  Python
关注(0)|答案(2)|浏览(330)
    • bounty将在6天后过期**。回答此问题的人有资格获得+150的声望奖励。Lumo希望吸引更多人关注此问题。

我使用的是https://github.com/ekonda/kutana
plugins/test.py:

from kutana import Plugin
import pickle

plugin = Plugin(name="Tictactoe",
                description="Tictactoe Game",
                invites={},
                games=[])

@plugin.on_start()
async def _():
    plugin.games = [Game()]

# Backup games when bot is shutting down
@plugin.on_shutdown()
async def _():
    try:
        with open("games.pickle", "wb") as f:
            pickle.dump(plugin.games, f)
    except Exception as e:
        print(e)

class Game:
    def __init__(self):
        pass

run.py:

from kutana import Kutana, load_plugins

# Create application
app = Kutana()

# Load and register plugins
app.add_plugins(load_plugins("plugins/"))

if __name__ == "__main__":
    # Run application
    app.run()

plugin.games为空时,pickle转储时没有错误,但是如果我在这里放置class Game的任何已创建对象,则在尝试备份时会出现错误:

Traceback (most recent call last):
  File "C:\Users\root\Desktop\Celestiana\plugins\games\tictactoe.py", line 17, in _
    pickle.dump(pl.games, f)
_pickle.PicklingError: Can't pickle <class 'plugins/games\tictactoe.py.Game'>: import of module 'plugins/games\\tictactoe.py' failed

我该如何修复它?我尝试做一些类似pickle.dump(plugin.games, f, fix_imports=True)的事情,但它不起作用。
重现此错误的示例项目:https://github.com/daeeros/example

46scxncf

46scxncf1#

修复直接导入Python源文件的方式。
1.在load_plugins_from_file中,指定正确的名称。

def load_plugins_from_file(path, verbose=False):
    ...

    # mod = import_module(path, path)              # Change this
    name = path.split(".py")[0].replace("/", ".")  # to these
    mod = import_module(name, path)                # two lines

    ...

1.在定制的import_module中,将模块插入sys.modules,如食谱www.example.com所示https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly。

def import_module(name, path):
    ...

    spec = importlib.util.spec_from_file_location(name, os.path.abspath(path))
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module  # Add this
    spec.loader.exec_module(module)

    return module
00jrzges

00jrzges2#

试试看

game = Game(ctx, chat_id, players)
# Add the game to the list of games
pl.games.append(game)

# Backup the games when shutting down
@pl.on_shutdown()
async def _():
    try:
        with open("games.pickle", "wb") as f:
            pickle.dump(pl.games, f)
    except Exception as e:
        print(e)

相关问题