Код, вставленный ниже, делает следующее:
- создает ловушку для импорта
- создает менеджер контекста, который устанавливает
meta_path
и очищает при выходе.
- сбрасывает весь импорт, выполненный программой, переданной во входных данных в import.log
Теперь мне стало интересно, является ли использование контекстного менеджера хорошей идеей в этом случае, потому что на самом деле у меня нет стандартного потока try/finally
, а просто настройка и очистка.
Другое дело - с этой строкой:
with CollectorContext(cl, sys.argv, 'imports.log') as cc:
cc
становится None
? Разве это не должен быть CollectorContext
объект?
from __future__ import with_statement
import os
import sys
class CollectImports(object):
"""
Import hook, adds each import request to the loaded set and dumps
them to file
"""
def __init__(self):
self.loaded = set()
def __str__(self):
return str(self.loaded)
def dump_to_file(self, fname):
"""Dump the loaded set to file
"""
dumped_str = '\n'.join(x for x in self.loaded)
open(fname, 'w').write(dumped_str)
def find_module(self, module_name, package=None):
self.loaded.add(module_name)
class CollectorContext(object):
"""Sets the meta_path hook with the passed import hook when
entering and clean up when exiting
"""
def __init__(self, collector, argv, output_file):
self.collector = collector
self.argv = argv
self.output_file = output_file
def __enter__(self):
self.argv = self.argv[1:]
sys.meta_path.append(self.collector)
def __exit__(self, type, value, traceback):
# TODO: should assert that the variables are None, otherwise
# we are quitting with some exceptions
self.collector.dump_to_file(self.output_file)
sys.meta_path.remove(self.collector)
def main_context():
cl = CollectImports()
with CollectorContext(cl, sys.argv, 'imports.log') as cc:
progname = sys.argv[0]
code = compile(open(progname).read(), progname, 'exec')
exec(code)
if __name__ == '__main__':
sys.argv = sys.argv[1:]
main_context()