Python 将代码写入文件,并使用uuu import和reload()作为模块重新导入

Python 将代码写入文件,并使用uuu import和reload()作为模块重新导入,python,Python,我一直试图为我的程序实现uuu import_uuu()和reload(),但都没有成功,但我无法让它工作。我将一个字符串写入.py文件(模块),然后将其作为模块加载。然后我对该.py文件(模块)进行更改并写入,但我似乎无法在新更新的模块中获得要更改的返回值。这是我的密码: str1 = ''' def run(): return 10 ''' f = open('mycode.py','w') f.write(str1) f.close() mymodule = __import__

我一直试图为我的程序实现uuu import_uuu()和reload(),但都没有成功,但我无法让它工作。我将一个字符串写入.py文件(模块),然后将其作为模块加载。然后我对该.py文件(模块)进行更改并写入,但我似乎无法在新更新的模块中获得要更改的返回值。这是我的密码:

str1 = '''
def run():
    return 10

'''
f = open('mycode.py','w')
f.write(str1)
f.close()
mymodule = __import__('mycode')

es = 'number = mymodule.run()'
exec(es)
print "number", number


str2 = '''
def run():
    return 99

'''
f = open('mycode.py','w')
f.write(str2)
f.close()

mymodule = reload(mymodule)
mymodule = __import__('mycode')

es = 'number = mymodule.run()'
exec(es)
print "number", number


OUTPUT:
>> number 10
>> number 10 # should be 99
我在这里看过:

在这里:

在这里:

但我没能想出一个解决办法。任何帮助都将不胜感激。谢谢

保罗

编辑

我使用exec(es)的原因是,如果我有多个参数,我想自定义es。下面是一个例子:

p = [2,1]
p2 = [3,4,5]
p3 = [100,200,300,500]

str1 = '''
def run(x,y):
        return x + y

'''

with open('mycode.py','w') as f:
    f.write(str)
import mycode as mymodule

# how do i do this dynamically, 
# how to handle it when # of paremeters for run() change?
print mymodule.run(p[0],p[1])  # hard-coded parameter passing
# or, print mymodule.run(p[0],p3[1],p[2]) # if run() is changed

所以问题是我的run()可以有不同的参数。它可以是run(x,y)或run(larry,moe,curly,hickory,dickory,dock)。如何动态传递多个参数以运行()?谢谢。

您的实际问题很简单。我会解释如何修复它。但实际上,你不应该这样做。无论你想做什么,你都是做错了

并不是说任何人都没有理由想做这样的事。但我很有信心,任何使用
exec
的人都不会有这样的理由,因为他不知道你可以将函数作为一级值传递,用文本模块名调用
\uuuuuuuuuuuuuu
。如果你解释你实际上想做什么,我们可以解释

但与此同时:

当您执行第一次
导入
时,它正在创建一个
mycode.pyc
文件,而
重新加载
只是重新加载该文件

您可以通过删除
mycode.pyc
,然后运行
python-B reloadtest.py
而不是
python reloadtest.py
来验证这一点。这显然给了你一个可能的解决办法

或者,您可以在调用
reload
之前显式地
os.unlink('mycode.pyc')
。我想大多数人都会认为这是一个非常大胆的想法,但我不认为这比你最初想要做的要多。

最后,如果您创建了一个新的
mycode.py
文件,而不是原地重写现有文件,我认为这将解决问题


同时,您的代码与下面的代码完全相同。(为了解决您在评论中的困惑:完全相同意味着它将有完全相同的问题,并且完全相同的解决方案将解决它。)它也更简单、更pythonic、更易于调试,因为它只涉及一个巨大的反模式(使用除交互式解释器之外的任何地方重新加载),而不是四个:

str1 = '''
def run():
    return 10

'''
with open('mycode.py', 'w') as f:
    f.write(str1)
import mycode as mymodule

print "number", mymodule.run()

str2 = '''
def run():
    return 99

'''
with open('mycode.py', 'w') as f:
    f.write(str2)

reload(mymodule)

print "number", mymodule.run()

在编辑中,您解释说您使用的是
exec
,因为您希望传递数量动态可变的参数:

它可以是run(x,y)或run(larry,moe,curly,hickory,dickory,dock)。如何动态传递多个参数以运行()

简单。只需将
x,y
larry,moe,curly,hickory,dickory,dock
放入
元组
列表
,或其他序列中,然后使用
run(*seq)

例如,我假设您有如下代码:

es = 'number = mymodule.run({})'.format(','.join(params))
exec(es)
def make_new_module(n):
    str = '''
    def run():
        return {}        
    '''.format(n)
    f = open('mycode.py','w')
    f.write(str1)
    f.close()
    return __import__('mycode')
def run_function_factory(n):
    def run_function(a, b):
        return a*n + b

run1 = run_function_factory(10)
for x in range(3):
    for y in range(2,5):
        print(run1(x,y)) # prints 2,3,4,12,13,14,22,23,24 (one per line)
您可以将其替换为:

number = mymodule.run(*params)
事实上,几乎在任何情况下,你都可以想象在你认为需要执行的地方,有更好的方法。如果你想不出答案,你可以在谷歌或StackOverflow上快速搜索,如果找不到答案,就问问怎么做。使用
exec
进行动态代码生成对于tcl来说是惯用的,几年前它也曾用于PHP和JavaScript,但在Python中这几乎从来都不是正确的做法

而且,正如您现在可能猜到的,动态创建模块以导入/
重新加载
/
执行文件
/等也是如此

例如,您的真实代码可能正在尝试执行以下操作:

es = 'number = mymodule.run({})'.format(','.join(params))
exec(es)
def make_new_module(n):
    str = '''
    def run():
        return {}        
    '''.format(n)
    f = open('mycode.py','w')
    f.write(str1)
    f.close()
    return __import__('mycode')
def run_function_factory(n):
    def run_function(a, b):
        return a*n + b

run1 = run_function_factory(10)
for x in range(3):
    for y in range(2,5):
        print(run1(x,y)) # prints 2,3,4,12,13,14,22,23,24 (one per line)
但您可以随时定义函数:

def make_new_function(n):
    def run():
        return n
    return run
如果您确实需要将其命名为
mymodule.run
,您可以轻松地创建一个名称空间,如类、类实例、
namedtuple
等,以将其固定

如果确实需要,您甚至可以动态创建新模块(尽管我敢打赌您不需要):

在现有模块中重新绑定函数更容易:

def change_mymodule_run(n):
    def run():
        return n
    mymodule.run = run
是的,模块是一级值,就像函数一样,因此如果
module
是一个动态参数而不是静态值,那么您也可以轻松地执行此操作:

def change_module_run(module, n):
    def run():
        return n
    module.run = run

正如一些评论者所说,您可能不需要编写模块来获得动态代码。下面是一个替代实现,它创建了两个不同版本的
run
函数,它们给出了不同的结果:

def run_function_factory(n):
    def run_function():
        return n
    return run_function

run1 = run_function_factory(10)
print("run1 returns", run1()) # prints "run1 returns 10"

run2 = run_function_factory(99)
print("run2 returns", run2()) # prints "run2 returns 99"
显然,实际的代码将更加复杂,但对于几乎所有需要的变体,都应该有类似的编码风格(将函数视为一级对象)。例如,如果
run
接受两个参数,
a
b
,并在返回之前对它们和
n
进行一些算术运算,您可以使用如下方法:

es = 'number = mymodule.run({})'.format(','.join(params))
exec(es)
def make_new_module(n):
    str = '''
    def run():
        return {}        
    '''.format(n)
    f = open('mycode.py','w')
    f.write(str1)
    f.close()
    return __import__('mycode')
def run_function_factory(n):
    def run_function(a, b):
        return a*n + b

run1 = run_function_factory(10)
for x in range(3):
    for y in range(2,5):
        print(run1(x,y)) # prints 2,3,4,12,13,14,22,23,24 (one per line)

我知道我没有回答这个问题,但是如果您想在运行时创建新的行为,那么这不是一种方法。在Python中,您可以在运行时重新定义和修补类,而无需
reload()
reload
机制充其量是脆弱的——它是用于REPL的,而不是用于编程用途。如果您确实想替换模块,您可以随时访问
sys.modules
。这就是
pythonsh
所做的,例如,与此同时,为什么在这里使用
exec
,而不仅仅是
number=mymodule.run()
?你期望它做些不同的事情吗?(如果是的话,是什么?)或者只是增加了更多的复杂性,使问题变得更加困难?我使用exec()是因为我希望能够