我有一个包含很多变量的python模块。许多其他模块使用和更改这些变量。我想在它发生时重新加载这个模块(刷新)。
怎么做?
# ==================================
# foo.py
spam = 100
def set_spam(value):
spam = value
foo = reload(foo) # reload module from itself
# ==================================
# bar.py
import foo
print foo.spam # I expect 100
# assume that value changes here from some another modules (for example, from eggs.py, apple.py and fruit.py)
foo.set_spam(200)
print foo.spam # I expect 200
答案 0 :(得分:3)
你想要实现的目标有很多问题,除非你故意设置一个自我修改的代码系统,它看起来不像你。
spam = 100
def set_spam(value):
spam = value
foo = reload(foo) #reload module from itself
这不起作用。由于Python闭包的工作原理,您的spam = value
行将在spam
函数中创建一个新的本地变量set_spam
,然后不会被使用。要正确更改全局spam
的值,您必须使用global
关键字,因此:
spam = 100
def set_spam(value):
global spam
spam = value
据我所知,实际上没有办法实现这一点,也不需要。您import
- ed的任何模块都会从其他模块调用,一直到__main__
。您只需从该调用模块刷新它。是的,你可以尝试自我导入一个模块(虽然可能存在无限循环问题,如mgilson所述),但即便如此(使用名为“foo”的例子),如果你有它导入本身,您只需要foo.foo
,并执行类似foo.reload(foo)
的操作(如果这甚至有效)只会重新加载子foo
,而不是基础。{/ p>
foo.py
# ==================================
# foo.py
spam = 100
def set_spam(value):
global spam
spam = value
请注意,在此代码的顶部,您将100分配给spam
。 每次导入模块时,您都会再次执行此操作。因此,即使您已经在导入的代码spam
中更改了foo
的值,当您重新加载模块时,您实际上也会破坏您刚才所做的更改。例如:
>>> import foo
>>> foo.spam
100
>>> foo.spam = 9
>>> foo.spam
9
>>> reload(foo)
>>> foo.spam
100
因此,如果您想保留对foo
中的变量所做的更改,则应不重新加载模块。此外,您甚至不需要使用set_spam
函数来更改spam
,您可以像我一样直接设置它。
最后,如果我理解你正在尝试做什么,那就不行了。这在很大程度上是因为我在第3部分中提到的内容,其中每次加载foo
时,spam=100
行都会重置spam
的值。同样,如果您在两个不同的其他模块中导入foo
模块,当每个模块都导入它时,它们将分别从spam = 100
开始,完全独立于其他模块的模块。与foo.spam
。例如,如果bar1.py
和bar2.py
都包含行import foo
:
>>> import bar1, bar2
>>> bar1.foo.spam
100
>>> bar2.foo.spam
100
>>> bar1.foo.spam = 200
>>> bar1.foo.spam
200
>>> bar2.foo.spam
100
有关您正在尝试执行的操作的更多说明,我们可以帮助您重新构建代码,使其更好地运行。
答案 1 :(得分:2)
在Python 2.6.2中,它很简单。假设您的模块名为“t”,定义如下:
import imp
def reload():
name="t"
imp.load_module(name,*imp.find_module(name))
print("loaded")
加载此模块后,添加另一个成员并执行t.reload()。
P.S。我想每个人都认为这是一个坏主意:它们可能是正确的,但如果你是交互式地开发模块,那么它可能会让事情变得更加方便。只需在将代码分发给其他人之前将其删除,否则他们可能会感到困惑。
答案 2 :(得分:1)
我不知道如何干净利落地做到这一点而不会陷入无限循环。也许最好有一个reset
函数?
def reset():
global spam
spam = 100
请注意,这个设计对我来说似乎有点时髦。从长远来看,似乎更好的数据封装可能对你有很大的帮助 - 或许类似于:
def new_namespace():
return {'spam':100}
然后,您的每个其他函数都可以接受命名空间字典作为参数,而不是依赖于foo
命名空间。
答案 3 :(得分:1)
此操作根本不会产生任何感觉。来自Python documentation:
重新加载(模块):重新加载以前导入的模块。参数必须是模块对象,因此必须先成功导入。
因此,reload
仅使用先前执行import
的其他模块的上下文来表示感知。
答案 4 :(得分:1)
下面
import sys
reload(sys.modules[__name__])
注意,这不适用于main
模块,但适用于任何其他模块。
答案 5 :(得分:1)
您还可以计算模块重新加载的次数!:
import importlib
import sys
count = 0
var = 0
def refresh():
global count
c = count
importlib.reload(sys.modules[__name__])
count = c + 1
print (f'reloaded {count} time(s)')
import mymodule
mymodule.var = 'changed'
mymodule.refresh()
# -> reloaded 1 times(s)
print(mymodule.var)
# -> 0
mymodule.refresh()
# -> reloaded 2 times(s)
答案 6 :(得分:0)
这是先前答案的另一个版本,计数器仅在不存在时才初始化。在 python 3.8.6 上测试
# mod.py
import importlib, sys
a=0
def reload():
importlib.reload(sys.modules[__name__])
global i
try:
i += 1
except:
i = 1
print(f'reloaded {i} time(s)')
# main.py
import mod
mod.a = 10
print (mod.a) # -> 10
mod.reload() # -> reloaded 1 time
print (mod.a) # -> 0
mod.reload() # -> reloaded 2 times