Python exec使用:locals,golobals传参读取返回值

本文详细介绍了Python的exec函数,它能执行存储在字符串或文件中的Python语句,支持定制全局和局部变量。通过示例展示了如何使用exec执行类定义和函数,并解释了为何在特定情况下需要分开执行代码来避免作用域问题。同时提到了限制代码使用内置函数的方法。
摘要由CSDN通过智能技术生成

简介

exec 执行储存在字符串或文件中的Python语句,相比于 eval,exec可以执行更复杂的 Python 代码,等同于可以执行整个py文件。

简单示例:

>> exec('foobar = 123')
>>> foobar
123

 exec 函数还支持可选参数 :

exec(object[, globals[, locals]])

这两个参数可以用来指定执行代码时可以使用的全局变量和局部变量, 以及收集执行代码后的全局变量和局部变量。

  • globals 默认为 globals()
  • locals 默认为 globals 参数的值

 

globals

globals 是个 dict 对象,用来指定代码执行时可以使用的全局变量以及收集代码执行后的全局变量:

>>> age = 10
>>> exec('abc = age + 1')
>>> exec('abc = age + 1', {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'age' is not defined
>>> exec('abc = age + 1', {'age': 2})
>>>
>>> g = {'age': 2}
>>> exec('abc = age + 1', g)
>>> g['abc'], g['age']
(3, 2)

如果只指定了 globals 参数,它的值将同样用于 locals 参数。

有一点需要注意的是: 当 globals 字典不包含 __builtins__ 这个 key 时, python 会自动加一个指向 builtins 的引用。所以如果要禁止/限制代码使用内置函数的话, 需要同时指定 __builtins__ 这个 key:

>>> exec('int(1)', {})

>>> exec('int(1)', {'__builtins__': {}})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'int' is not defined

locals

locals 可以是任何 mapping 对象,用来指定代码执行时的局部变量以及收集代码执行后的局部变量:

>>> exec('abc = age + 1', {}, {'age': 2})
>>>
>>> local = {}
>>> exec('''
... name = 'Tom'
... age = 13
... ''', {}, local)

>>> local
{'age': 13, 'name': 'Tom'}

指定locals函数内locals被改变

如果指定了locals参数,那字符串中locals不会生效,如你先定义一个类,再在函数中调用时,函数会报没有定义:

code = """
class Code():
    def __init__(self):
        print("okok=============")

def test(a):
    print("函数内的locals:", locals())
    c = Code()
    return a
print("函数外的locals:", locals())
a = test(a)
"""

print("编译主代码前locals:", locals())
hh = {}
a = 8888
exec(code, locals(),hh)
print("执行主函数后locals:", locals())
print(hh)


编译主代码前locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1059ac470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\na = test(a)\n'}
函数外的locals: {'Code': <class '__main__.Code'>, 'test': <function test at 0x105922e18>}
函数内的locals: {'a': 8888}
Traceback (most recent call last):
  File "/Users/logen/PycharmProjects/code/code2.py", line 17, in <module>
    exec(code, locals(),hh)
  File "<string>", line 11, in <module>
  File "<string>", line 8, in test
NameError: name 'Code' is not defined

 

如果不传locals参数

code = """
class Code():
    def __init__(self):
        print("okok=============")

def test(a):
    print("函数内的locals:", locals())
    c = Code()
    return a
print("函数外的locals:", locals())
a = test(a)
"""

print("编译主代码前locals:", locals())
hh = {}
a = 8888
exec(code, locals())
print("执行主函数后locals:", locals())
print(hh)


编译主代码前locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x103723470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\na = test(a)\n'}
函数外的locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x103723470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\na = test(a)\n', 'hh': {}, 'a': 8888, 'Code': <class '__main__.Code'>, 'test': <function test at 0x103699e18>}
函数内的locals: {'a': 8888}
okok=============
执行主函数后locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x103723470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\na = test(a)\n', 'hh': {}, 'a': 8888, 'Code': <class '__main__.Code'>, 'test': <function test at 0x103699e18>}
{}

 

解决办法:将传参的代码分开执行

code = """
class Code():
    def __init__(self):
        print("okok=============")

def test(a):
    print("函数内的locals:", locals())
    c = Code()
    return a
print("函数外的locals:", locals())

"""
run = "a = test(a)"
print("编译主代码前locals:", locals())
exec(code)
print("编译主代码后locals:", locals())


hh = {}
a = 8888
exec(run, locals(),hh)
print("执行主函数后locals:", locals())
print(hh)


编译主代码前locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10e351470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\n\n', 'run': 'a = test(a)'}
函数外的locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10e351470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\n\n', 'run': 'a = test(a)', 'Code': <class '__main__.Code'>, 'test': <function test at 0x10e2c7e18>}
编译主代码后locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10e351470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\n\n', 'run': 'a = test(a)', 'Code': <class '__main__.Code'>, 'test': <function test at 0x10e2c7e18>}
函数内的locals: {'a': 8888}
okok=============
执行主函数后locals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10e351470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/logen/PycharmProjects/code/code2.py', '__cached__': None, 'code': '\nclass Code():\n    def __init__(self):\n        print("okok=============")\n\ndef test(a):\n    print("函数内的locals:", locals())\n    c = Code()\n    return a\nprint("函数外的locals:", locals())\n\n', 'run': 'a = test(a)', 'Code': <class '__main__.Code'>, 'test': <function test at 0x10e2c7e18>, 'hh': {'a': 8888}, 'a': 8888}
{'a': 8888}

 

 

参考资料

1. https://mozillazg.com/2016/03/python-exec-function-globals-and-locals-arguments.html

2. Built-in Functions — Python 3.5.1 documentation

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值