简介

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

Python exec使用:locals,golobals传参读取返回值相关推荐

  1. 【php7扩展开发四】函数的参数 ,引用传参 ,返回值

    函数参数解析 之前我们定义的函数没有接收任何参数,那么扩展定义的内部函数如何读取参数呢?用户自定义函数在编译时会为每个参数创建一个zend_arg_info结构,这个结构用来记录参数的名称.是否引用传 ...

  2. java中注解动态传参_SpringMVC之注解、传参、返回值及拦截器

    1. 注解式开发之annotation-driven解释 (1) mvc注解驱动在哪个文件中配置? Springmvc.xml (2) 配置mvc注解驱动使用哪个标签? 2. 注解式开发之视图解析器 ...

  3. 【Python】多线程的使用,通过传参接收返回值

    参考:廖雪峰的官方网站 Python多线程 多任务可以由多进程完成,也可以由一个进程内的多线程完成. 我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程. 由于线程是操作系统直接支持的执行单 ...

  4. 深入理解PHP内核(十二)函数-函数的定义、传参及返回值

    原文链接:http://www.orlion.ga/344/ 一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) { echo $var; } 1 ...

  5. 多维数组之二维数组传参、返回值、申请内存问题

    目录 多维数组 存储顺序 二维数组基础知识 数组名 下标 指向数组的指针 二维数组使用 初始化 作为函数参数的二维数组 二维数组返回值与申请内存问题 多维数组 如果某个数组的维数不止1个,它就被称为多 ...

  6. python的py文件打包exe可执行文件(传参+读取文件)

    python打包成可执行文件用pyinstaller即可完成 但是如果需要考虑传参和读取文件,就显得不是那么丝滑了.(找了蛮久才解决的) 下面将展示如何完成打包后的exe文件实现能够传参+读取文件 首 ...

  7. 关于Python、C语言的传参问题

    关于Python与c语言的传参问题 Python中 c语言中 要理解Python中的变量与c语言中的变量是不同的.很重要!!!!!!!!!!!!!!!!! 我们都知道函数的参数分为形参和实参. 形参就 ...

  8. 【C语言】二十二步了解函数栈帧(压栈、传参、返回、弹栈)

    阅读本文需要掌握的知识 熟练使用--c语言函数 进入正题前 首先我们为什么要学习函数的栈帧? 简单回答就是:增加内功 学习函数调用的底层代码,了解函数如何传参.如何返回 这样对于函数的使用有很大的帮助 ...

  9. shell函数传参和返回

    文章目录 一.一个简单shell函数 二.shell函数传参 三.shell函数返回结果 一.一个简单shell函数 #!/bin/bash function SayHi() {echo " ...

最新文章

  1. 何恺明、吴育昕最新成果:用组归一化替代批归一化
  2. 差异备份、增量备份、完全备份的区别
  3. 简单几行代码带你快速了解淘宝双十一的强大技术支撑点Sentinel+Nacos
  4. 牛客题霸 NC4 判断链表中是否有环
  5. play 框架_用于Play框架分布式应用程序的Init.d Shell脚本
  6. MySql的用户权限
  7. 黑侠百度URL批量推送程序
  8. 小汤学编程之JAVA基础day03——运算符
  9. 测试开发字节跳动(二面),我被面试官按在地上摩擦!
  10. 数字图像处理(一) 绪论
  11. IDEA打包war部署到Tomcat
  12. UVALive 6437 Power Plant 【最小生成树 + 思维】
  13. Google Chrome如何恢复误删除书签和文件夹
  14. 你以为你了解Kaggle吗?| 超级干货
  15. scandef格式详细说明
  16. JavaWeb正则表达式2-不情愿模式
  17. 【无题】2022-1
  18. python生成的excel无法打开-Python 解决中文写入Excel时抛异常的问题
  19. 掌握web开发基础系列--物理像素、逻辑像素、css像素
  20. FCC学习记录——使用 sort方法按字母顺序给数组排序

热门文章

  1. Spring知识点总结归纳。
  2. ubuntu16.04下gpu版caffe2安装
  3. Element时间转换时间戳
  4. marquee标签 html5,HTML+CSS入门 marquee标签详解
  5. stm32 串口输出 中文乱码
  6. mcp918使用教程(MineCraft 1.8.8反编译)
  7. Android系统修改userdata分区大小
  8. 米思齐学习例程(三):按键
  9. Foundog:用电子标签跟踪你的物品【cnbeta,2010.3.25】(陈礼彬转)
  10. 移植RTT--官方教程