为了减少基于Python的Web应用程序的开发时间,我试图对我最近修改过的模块使用reload().reload()通过专用网页(Web应用程序的开发版本的一部分)进行,该网页列出了最近修改过的模块(并且py文件的修改时间戳晚于相应的pyc文件).完整的模块列表是从sys.modules获得的(我过滤列表只关注那些属于我的包的模块).
重新加载单个python文件似乎在某些情况下有效,而在其他情况下则无效.我想,所有依赖于修改过的模块的模块都应该重新加载,重新加载应该按照正确的顺序进行.
我正在寻找一种方法来获取特定模块导入的模块列表.有没有办法在Python中进行这种内省?
我知道我的方法可能不是100%保证,最安全的方法是重新加载所有内容,但如果快速方法适用于大多数情况,那么它对于开发目的来说已经足够了.
回复关于DJango autoreloader的评论
@Glenn Maynard,Thanx,我读过有关DJango自动重载器的内容.我的Web应用程序基于Zope 3以及包的数量和大量基于ZCML的初始化,如果数据库大小更大,则总重启大约需要10秒到30秒或更长时间.我试图减少重启期间花费的这段时间.当我觉得我做了很多改变时,我通常更喜欢完全重启,但更多的时候我会改变这里和那里的几行,我不想花那么多时间.开发设置完全独立于生产设置,通常如果重新加载出现问题,由于应用程序页面开始显示不合逻辑的信息或抛出异常,因此很明显.我非常有兴趣探索选择性重载是否有效.
所以 - 这回答"查找依赖于给定模块的模块列表" - 而不是问题的初始措辞 - 我在上面回答了这个问题.
事实证明,这有点复杂:必须为所有加载的模块找到依赖树,并为每个模块反转它,同时保留不会破坏事物的加载顺序.
我还把它发布到了brazillian的python wiki:http://www.python.org.br/wiki/RecarregarModulos
#! /usr/bin/env python
# coding: utf-8
# Author: João S. O. Bueno
# Copyright (c) 2009 - Fundação CPqD
# License: LGPL V3.0
from types import ModuleType, FunctionType, ClassType
import sys
def find_dependent_modules():
"""gets a one level inversed module dependence tree"""
tree = {}
for module in sys.modules.values():
if module is None:
continue
tree[module] = set()
for attr_name in dir(module):
attr = getattr(module, attr_name)
if isinstance(attr, ModuleType):
tree[module].add(attr)
elif type(attr) in (FunctionType, ClassType):
tree[module].add(attr.__module__)
return tree
def get_reversed_first_level_tree(tree):
"""Creates a one level deep straight dependence tree"""
new_tree = {}
for module, dependencies in tree.items():
for dep_module in dependencies:
if dep_module is module:
continue
if not dep_module in new_tree:
new_tree[dep_module] = set([module])
else:
new_tree[dep_module].add(module)
return new_tree
def find_dependants_recurse(key, rev_tree, previous=None):
"""Given a one-level dependance tree dictionary,
recursively builds a non-repeating list of all dependant
modules
"""
if previous is None:
previous = set()
if not key in rev_tree:
return []
this_level_dependants = set(rev_tree[key])
next_level_dependants = set()
for dependant in this_level_dependants:
if dependant in previous:
continue
tmp_previous = previous.copy()
tmp_previous.add(dependant)
next_level_dependants.update(
find_dependants_recurse(dependant, rev_tree,
previous=tmp_previous,
))
# ensures reloading order on the final list
# by postponing the reload of modules in this level
# that also appear later on the tree
dependants = (list(this_level_dependants.difference(
next_level_dependants)) +
list(next_level_dependants))
return dependants
def get_reversed_tree():
"""
Yields a dictionary mapping all loaded modules to
lists of the tree of modules that depend on it, in an order
that can be used fore reloading
"""
tree = find_dependent_modules()
rev_tree = get_reversed_first_level_tree(tree)
compl_tree = {}
for module, dependant_modules in rev_tree.items():
compl_tree[module] = find_dependants_recurse(module, rev_tree)
return compl_tree
def reload_dependences(module):
"""
reloads given module and all modules that
depend on it, directly and otherwise.
"""
tree = get_reversed_tree()
reload(module)
for dependant in tree[module]:
reload(dependant)
Run Code Online (Sandbox Code Playgroud)
这在我在这里所做的所有测试中都很好看 - 但是我不会反复滥用它.但是为了在编辑几行代码后更新正在运行的zope2服务器,我想我会自己使用它.
归档时间: |
|
查看次数: |
1805 次 |
最近记录: |