我正在编写一个Python程序,以在Verilog脚本中执行嵌入式Python代码。我曾考虑使用eval
和exec
函数,但遇到一个问题:我想让所有exec
和eval
在共享< em> context ,而无需更改主程序的环境。
我将exec
和eval
放在函数中以调用解析例程:
# some parsing code
for embedded_code_string in list_of_embedded_code_strings:
execute_embedded_code(embedded_code_string)
# more parsing code
def execute_embedded_code(embedded_code_string):
exec(embedded_code_string)
# other routines involving io.StringIO for the redirection of stdout which isn't the problem.
如果要运行的第一个嵌入式代码字符串是row_len = 1
,而第二个是column_len = row_len * 2
,则在运行第二个代码片段时,row_len
将是未定义的。可以预期:毕竟,exec
在函数execute_embedded_code
的上下文中运行,并且在函数完成后,变量将从locals()
和globals()
中消失。
看来您可以为exec
设置本地和全局名称空间。但是,运行exec
后的更改将不会就地保留。 (更正:global_dict和local_dict参数必须为字典,否则将被忽略。如果它是字典,则将被就地更新。。)运行globals()
和{{ locals()
之后的1}}会捕获更改,但也会捕获解析程序中的对象,因此,我不希望嵌入的代码无意中弄乱了解析程序。
所以我的问题是,我将如何在它们的共享上下文中运行许多exec
调用,但又要足够孤立以至于它们不会产生意想不到的后果。无需考虑安全性,因为运行中的所有嵌入式代码都将受到信任。
我想获得每个嵌入式代码字符串的单独输出,因此我不认为将它们连接在一起并一次运行就可以了。
答案 0 :(得分:1)
您应该能够定义自己的共享FactoryBot.define do
factory :my_model do
bar { 'abc' }
transient do
default_values true
end
before(:create) do |my_model, evaluator|
if evaluator.default_values?
foo { 'abc' }
end
end
trait(:foo_not_set) do
transient do
default_values { false }
end
end
end
end
,并将其传递给globals
,然后由嵌入代码对其进行修改:
exec
输出
def execute_embedded_code(embedded_code_string, shared_globals):
exec(embedded_code_string, shared_globals)
shared_globals = dict()
shared_globals['result'] = 0
sample_string = 'result += 1'
execute_embedded_code(sample_string, shared_globals)
print(shared_globals['result'])
注意
要在下面发表评论,请documentation for exec声明
如果仅提供 globals ,则必须为字典,该字典将用于全局变量和局部变量。