【问题标题】:importlib.reload() not realoadingimportlib.reload() 不重新加载
【发布时间】:2021-05-13 23:52:18
【问题描述】:

我正在尝试创建一个像在线法官一样的 leetcode。我需要重新加载提交模块,但import.reload() 不起作用。

代码:

class Test:
    current_exercise = None
    current_name = None

    def _import(self, exercise):
        exercise = 'exercise'    # for testing 

        if exercise == self.current_name:
            module = sys.modules[f'puzzles.{exercise}']
            self.current_exercise = importlib.reload(module)    # <---- not working 
        else:
            self.current_name = exercise
            self.current_exercise = __import__(f'puzzles.{exercise}').exercise

    def _test(self, exercise):
        solution = self._import(exercise)
        print(self.current_exercise.main())

if __name__=='__main__':
    import shutil
    t= Test()

    # first run 
    t._test('exercise')
    
    # copy another solution.py for reload test
    shutil.copy(f"./puzzles/other_exercise/solution.py", f"./puzzles/exercise/solution.py")

    # second run 
    t._test('exercise')

我的目录;

.
├── codetest.py
├── puzzles
│   ├── __init__.py
│   ├── exercise
│   │   ├── __init__.py
│   │   ├── solution.py
│   ├── other_exercise
│   │   ├── __init__.py
│   │   ├── solution.py

练习/solution.py:

def main(): 
    print('EXERCISE')

练习/初始化.py

​​>
from .solution import main
from .test import cases

other_exercise/solution.py:

def main(): 
    print('OTHER EXERCISE')

输出:

> EXERCISE
> EXERCISE   # <--- not sucessfull, should be 'OTHER EXERCISE'

【问题讨论】:

  • .p0 在您的__import__ 行末尾做什么?
  • 其他方式都行不通。
  • 有趣。您的 __init__.py 文件中有什么内容?除非有人导入了solution,否则main() 将不可用。
  • 一个有用的提示:您应该将不推荐的__import__ 替换为importlib.import_module(f"puzzles.{exercise}")。它没有解决根本问题,但确实消除了对额外.exercise 后缀的需要。
  • 问题似乎是重新导入“puzzles/exercise”对重新导入solutions.py没有任何作用。如果您将重新导入行更改为self.current_exercise.solution = importlib.reload(self.current_exercise.solution),那么它可以工作。

标签: python python-3.x python-importlib


【解决方案1】:

这行得通:

import sys
import time
import importlib

class Test:
    current_exercise = None
    current_name = None

    def _import(self, exercise):

        if exercise == self.current_name:
            self.current_exercise.solution = importlib.reload(self.current_exercise.solution)
        else:
            self.current_name = exercise
            self.current_exercise = importlib.import_module(f'puzzles.{exercise}')
        print('mod',self.current_exercise)
        print('nam',self.current_exercise.__name__)
        print('fil',self.current_exercise.__file__)
        print('pkg',self.current_exercise.__package__)

    def _test(self, exercise):
        solution = self._import(exercise)
        print(self.current_exercise.solution.main())

if __name__=='__main__':
    import shutil
    shutil.copy(f"./puzzles/exercise/solution.0", f"./puzzles/exercise/solution.py")
    t= Test()

    # first run 
    t._test('exercise')
    
    # copy another solution.py for reload test
    shutil.copy("./puzzles/other_exercise/solution.py", "./puzzles/exercise/solution.py")
    print(open("./puzzles/exercise/solution.py").read())

    # second run 
    t._test('exercise')

【讨论】:

  • 使用time.perf_counter() 进行基准测试,加载文件比使用imp 加载代码更快:0.0005 与 0.0030。代码更简洁,但imp 已被弃用,我还没有针对同一模块的多次运行进行基准测试。 if 语句很昂贵。
  • 时间无关紧要。这只会在新提交时按需运行。
【解决方案2】:

我选择了另一种选择;将solution.py 加载为文本并从该字符串创建一个模块。该模块未在sys.modules 中注册,可以覆盖。但是 imp 已被弃用。

import imp

class Test:
    current_exercise = None

    def _import(self, exercise):

        # load module code 
        with open(f'./puzzles/{exercise}/solution.py') as f:
            code = f.read()

            # register/create the module
            self.current_exercise = imp.new_module('mymodule')

            # import/fill the module 
            exec(code, self.current_exercise.__dict__)

    def _test(self, exercise):
        self._import(exercise)
        print(self.current_exercise.main())

【讨论】:

    猜你喜欢
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    相关资源
    最近更新 更多