我正在尝试导入一个模块,同时传递一些全局变量,但它似乎不起作用:
文件test_1:
test_2 = __import__("test_2", {"testvar": 1})
文件test_2:
print testvar
这似乎应该可行,并打印1,但是当我运行test_1时出现以下错误:
Traceback (most recent call last):
File ".../test_1.py", line 1, in <module>
print testvar
NameError: name 'testvar' is not defined
我做错了什么?
修改
正如我稍后评论的那样,这是尝试替换图形库中的函数。这是一个使用该库的示例程序(我的老师写的):
from graphics import *
makeGraphicsWindow(800, 600)
############################################################
# this function is called once to initialize your new world
def startWorld(world):
world.ballX = 50
world.ballY = 300
return world
############################################################
# this function is called every frame to update your world
def updateWorld(world):
world.ballX = world.ballX + 3
return world
############################################################
# this function is called every frame to draw your world
def drawWorld(world):
fillCircle(world.ballX, world.ballY, 50, "red")
############################################################
runGraphics(startWorld, updateWorld, drawWorld)
请注意,此代码的设计使得之前(或几乎从未)看过任何代码的人(不仅仅是python)能够轻松理解。
重写函数的示例:
原始代码:
def drawPoint(x, y, color=GLI.foreground):
GLI.screen.set_at((int(x),int(y)), lookupColor(color))
注入的代码:
# Where self is a window (class I created) instance.
def drawPoint(x, y, color = self.foreground):
self.surface.set_at((int(x), int(y)), lookupColor(color))
我想我真正的问题是:在模块运行之前,如何将全局函数/变量注入导入的模块中??
答案 0 :(得分:7)
正如the docs解释的那样,globals
__import__
参数向 “注入”额外的全局变量到导入的模块中,正如您所认为的那样 - 实际上,通常传递的是导入模块的globals()
,因此如果发生这样的注入会很成问题。的确,__import__
的文档具体说:
标准实施没有 完全使用它的locals参数,和 仅使用其全局变量来确定 导入的包上下文 言。
修改:如果您确实需要注射,例如进入一个空的导入模块,正如OP在评论中建议的那样,只要你在>强导入后就可以了,这很容易:
themod = __import__(themodname)
themod.__dict__.update(thedict)
导入的模块的身体将不会注意到仍然发生的注射,但无论如何,这显然无论身体是否为空;-)。在导入之后,您可以注入您心中的内容,并且该模块的所有后续使用都会看到您的注射,就好像它们是真正的模块级绑定名称一样(因为它们是< / em>的; - 。)
如果你愿意的话,你甚至可以节省空的.py
模块的开头......:
import new, sys
themod = new.module(themodname)
sys.modules[themodname] = themod
themod.__dict__.update(thedict)
编辑:OP尝试在Q的编辑中澄清...:
我想我真正的问题是:怎么会 我注入全局函数/变量 进入之前的导入模块 模块运行......?
“模块运行”没有多大意义 - 模块被加载(执行它们的主体),只需一次(除非重新 - 稍后明确加载)......它们永远不会“运行” “本身。给定一个空模块,首先导入它(由于模块为空,因此不执行任何操作),如果您希望使用themodule.__dict__.update
和属性赋值的混合来填充模块,则可以使用 < / strong>刚刚提到时自动调用(因为OP表示担心他们会在评论中),所以他们可以被视为在这方面的任何其他变量(和大多数其他变量,这就是为什么Python说第一类功能)。
答案 1 :(得分:3)
我遇到了同样的问题...... 我用下面的技巧说服了自己...... 我不知道这对你有用还是有用的!
File2:test1.py
global myvar
myvar = "some initial value"
print myvar
test = __import__("test2")
print myvar
File2:test2.py
import inspect
stk = inspect.stack()[1]
myvar = inspect.getmodule(frm[0]).myvar
print myvar
myvar = "i am changing its value."
此变量从module1传递到module2 它也是通过引用传递的。
答案 2 :(得分:2)
如上所述,__import__
函数不会将全局变量添加到新模块中。如果你想这样做,我建议添加一些initialize()函数,为预先声明的全局表赋值,如下所示:
gTable = {}
gInited = False
def initialize(table):
if(not gInited):
gTable = table
gInited = True
def getGlobal(name):
if(name in gTable):
return gTable[name]
else:
throw NameError("name '"+name+"' is not defined")
def setGlobal(name, value):
gTable[name] = value
def mod_main():
print getGlobal("testvar")
并像这样导入:
import modGlobalsTest
modGlobalsTest.initialize({"testvar": 1})
modGlobalsTest.mod_main()
如果要更改导入库中的功能,可以执行以下操作:
import foobar
def bar(x):
return x+1
foobar.foo = bar
用自定义功能栏替换foobar.foo。
答案 3 :(得分:0)
你太努力了,你只需要简单的进口 在一个模块中定义变量,比如test1
testvar = 1
在test2中
import test1
print test1.testvar
答案 4 :(得分:0)
看起来您想要将代码注入图形库并使用它运行示例程序。如果是这样,你可以这样做:
import graphics
graphics.drawPoint = myDrawPoint
您还可以编写一个程序,将示例的文件名作为参数并执行:
import sys
import graphics
def main():
graphics.drawPoint = myDrawPoint
execfile(sys.argv[1])
答案 5 :(得分:0)
当我需要在加载时将全局变量传递给模块(这经常是),
我只需创建一个新的ModuleType
,将全局变量注入其命名空间,最后在该命名空间中执行我的源模块。
这是我的基本子模块导入代码:
(对于包,您需要__package__
和__path__
全局变量)
# such a headache to initialize a module requiring globals >_<
import sys,os, types.ModuleType as ModuleType
globals()['nodes'] = sys.modules['nodes'] = ModuleType('nodes') # set the namespace
nodes.__dict__.update(dict(
__name__ = 'nodes',
__file__ = __file__.replace(__name__,'nodes'),
# the globals I need in particular
GL = GL, # prevents a ghost (duplicate) import
drawText = drawText,
lenText = lenText ))
with open('nodes.py','rb') as src: exec( src.read(), nodes.__dict__ )
我不能只是import nodes
或者我会得到一个NameError,因为lenText
用于构建该模块中节点类的命中定义。
小贴士:在使用它时要小心!
对于我的情况,lenText
对每个字符的显示列表引用进行操作,因此我需要在准备GL上下文后专门导入。