Хм, ну одно я могу сказать, что функция timeit
фактически выполняет свой код, используя глобальные переменные модуля. Так что в вашем примере вы могли бы написать
import timeit
timeit.a = 1
timeit.b = 2
timeit.Timer('a + b').timeit()
и это бы сработало. Но это не решает более общую проблему динамического определения модуля.
Что касается проблемы определения модуля, то это определенно возможно, и я думаю, что вы наткнулись на практически лучший способ сделать это. Для справки, суть того, что происходит, когда Python импортирует модуль, в основном следующая:
module = imp.new_module(name)
execfile(file, module.__dict__)
Это примерно то же самое, что делаете вы, за исключением того, что вы загружаете содержимое модуля из существующего словаря, а не из файла. (Я не знаю никакой разницы между types.ModuleType
и imp.new_module
, кроме docstring, так что вы, вероятно, можете использовать их взаимозаменяемо) То, что вы делаете, сродни написанию собственного импортера, и когда вы это делаете, вы, конечно, можете ожидать, что будете возиться с sys.modules
.
В качестве отступления, даже если бы ваш import *
был законным внутри функции, у вас все равно могли бы возникнуть проблемы, потому что, как ни странно, оператор, который вы передаете в Timer
, похоже, не распознает свои собственные локальные переменные. Я вызвал немного вуду в Python по имени extract_context()
(это функция, которую я написал), чтобы установить a
и b
в локальной области видимости и запустил
print timeit.Timer('print locals(); a + b', 'sys.modules["__main__"].extract_context()').timeit()
Конечно, достаточно, распечатка locals()
включала a
и b
:
{'a': 1, 'b': 2, '_timer': <built-in function time>, '_it': repeat(None, 999999), '_t0': 1277378305.3572791, '_i': None}
но он все равно жаловался NameError: global name 'a' is not defined
. Странно.