动态模块创建 [英] dynamic module creation

查看:116
本文介绍了动态模块创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从字典动态创建一个模块,我想知道如果添加一个元素到 sys.modules 是真正的最佳方法。 EG

  context = {a:1,b:2} 
导入类型
test_context_module = types。 ModuleType('TestContext','模块创建以提供测试的上下文')
test_context_module .__ dict __。update(context)
import sys
sys.modules ['TestContext'] = test_context_module

我在这方面的直接目标是能够提供定时测试执行的上下文:

  import timeit 
timeit.Timer('a + b','from TestContext import *')

似乎还有其他的方法可以做到这一点,因为Timer构造函数接受对象和字符串。我仍然有兴趣学习如何做到这一点,因为a)它有其他潜在的应用程序;和b)我不知道如何使用Timer构造函数的对象;



EDITS / REVELATIONS / PHOOEYS / EUREKAE:




  1. 我已经意识到与运行计时测试相关的示例代码实际上不会起作用,因为 import * 只能工作在模块级别,执行该语句的上下文是 testit 模块中的函数 。换句话说,执行该代码时使用的全局变量字典是 __ main __ 的全局字典,因为这是当我在交互式shell中编写代码的时候。所以理解这一点的理由有点麻烦,但它仍然是一个有效的问题。


  2. 我发现代码运行在第一组示例具有不可取的影响,即新创建的模块的代码执行的命名空间是 的模块, em>自己的模块。这就像奇怪的,可能会导致各种意想不到的响尾蛇。所以我很确定这是不是这种事情是如何做的,如果事实上是Guido doth发光的东西。


  3. 使用 imp.load_source('NewModuleName)轻松实现从不在python包含路径中的文件动态加载模块的类似但不同的情况','path / to / module / module_to_load.py')。这将把模块加载到 sys.modules 中。但是,这并没有真正地回答我的问题,因为真的,如果你在嵌入式没有文件系统的平台


我正在与当前信息超载的相当大的情况,所以我可能会误会,但是在 imp 模块中似乎没有什么可以实现的。



但是,这个问题本质上就是如何设置对象的全局(即模块)上下文。也许我应该更具体地询问?而在更大的范围内,如何让Python做到这一点,同时将对象引入到给定的模块中?

解决方案

我可以告诉你的事情是, timeit 函数实际上使用模块的全局变量来执行其代码。所以在你的例子中,你可以写

  import timeit 
timeit.a = 1
timeit.b = 2
timeit.Timer('a + b')。timeit()

它会奏效但是,这并不能解决您更为一般地定义模块的一般问题。



关于模块定义问题,绝对有可能,我认为你已经绊倒了这是最好的方式。作为参考,Python导入模块时的要点基本如下:

  module = imp.new_module(name )
execfile(文件,模块.__ dict__)

这是一样的事情你做,除了您从现有字典而不是文件加载模块的内容。 (我不知道除了docstring之外的 types.ModuleType imp.new_module 之间的区别,所以你可能可以互换使用它们)你所做的一切类似于编写自己的进口商,当你这样做时,你一定会期待与$ code> sys.modules 混淆。另外,即使你的 import * 的东西在一个函数内是合法的,你可能仍然有问题,因为奇怪的是,您传递给 Timer 的声明似乎不能识别自己的局部变量。我调用了一些Python voodoo,名称为 extract_context()(这是我写的一个函数)来设置 a b 在本地范围并运行

  print timeit.Timer 'print locals(); a + b','sys.modules [__ main __]。extract_context()')。timeit()

果然, locals()的打印输出包含 a b

  {'a':1,'b' _timer':<内置函数时间>'_it':重复(无,999999),'_t0':1277378305.3572791,'_i':无} 

但仍然抱怨 NameError:全局名称'a'未定义。奇怪的。


I'd like to dynamically create a module from a dictionary, and I'm wondering if adding an element to sys.modules is really the best way to do this. EG

context = { a: 1, b: 2 }
import types
test_context_module = types.ModuleType('TestContext', 'Module created to provide a context for tests')
test_context_module.__dict__.update(context)
import sys
sys.modules['TestContext'] = test_context_module

My immediate goal in this regard is to be able to provide a context for timing test execution:

import timeit
timeit.Timer('a + b', 'from TestContext import *')

It seems that there are other ways to do this, since the Timer constructor takes objects as well as strings. I'm still interested in learning how to do this though, since a) it has other potential applications; and b) I'm not sure exactly how to use objects with the Timer constructor; doing so may prove to be less appropriate than this approach in some circumstances.

EDITS/REVELATIONS/PHOOEYS/EUREKAE:

  1. I've realized that the example code relating to running timing tests won't actually work, because import * only works at the module level, and the context in which that statement is executed is that of a function in the testit module. In other words, the globals dictionary used when executing that code is that of __main__, since that's where I was when I wrote the code in the interactive shell. So that rationale for figuring this out is a bit botched, but it's still a valid question.

  2. I've discovered that the code run in the first set of examples has the undesirable effect that the namespace in which the newly created module's code executes is that of the module in which it was declared, not its own module. This is like way weird, and could lead to all sorts of unexpected rattlesnakeic sketchiness. So I'm pretty sure that this is not how this sort of thing is meant to be done, if it is in fact something that the Guido doth shine upon.

  3. The similar-but-subtly-different case of dynamically loading a module from a file that is not in python's include path is quite easily accomplished using imp.load_source('NewModuleName', 'path/to/module/module_to_load.py'). This does load the module into sys.modules. However this doesn't really answer my question, because really, what if you're running python on an embedded platform with no filesystem?

I'm battling a considerable case of information overload at the moment, so I could be mistaken, but there doesn't seem to be anything in the imp module that's capable of this.

But the question, essentially, at this point is how to set the global (ie module) context for an object. Maybe I should ask that more specifically? And at a larger scope, how to get Python to do this while shoehorning objects into a given module?

解决方案

Hmm, well one thing I can tell you is that the timeit function actually executes its code using the module's global variables. So in your example, you could write

import timeit
timeit.a = 1
timeit.b = 2
timeit.Timer('a + b').timeit()

and it would work. But that doesn't address your more general problem of defining a module dynamically.

Regarding the module definition problem, it's definitely possible and I think you've stumbled on to pretty much the best way to do it. For reference, the gist of what goes on when Python imports a module is basically the following:

module = imp.new_module(name)
execfile(file, module.__dict__)

That's kind of the same thing you do, except that you load the contents of the module from an existing dictionary instead of a file. (I don't know of any difference between types.ModuleType and imp.new_module other than the docstring, so you can probably use them interchangeably) What you're doing is somewhat akin to writing your own importer, and when you do that, you can certainly expect to mess with sys.modules.

As an aside, even if your import * thing was legal within a function, you might still have problems because oddly enough, the statement you pass to the Timer doesn't seem to recognize its own local variables. I invoked a bit of Python voodoo by the name of extract_context() (it's a function I wrote) to set a and b at the local scope and ran

print timeit.Timer('print locals(); a + b', 'sys.modules["__main__"].extract_context()').timeit()

Sure enough, the printout of locals() included a and b:

{'a': 1, 'b': 2, '_timer': <built-in function time>, '_it': repeat(None, 999999), '_t0': 1277378305.3572791, '_i': None}

but it still complained NameError: global name 'a' is not defined. Weird.

这篇关于动态模块创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆