Python的exec

2023-11-14

目录

 

exec()简单使用

动态执行简单的字符串代码

动态执行较复杂的代码

执行文件中的Python代码

在exec中传参

使用中遇到的问题

参考


exec()简单使用

个人比较喜欢用Python里面的exec(),可以用来动态执行字符串代码,在for循环里面能快速执行大量类似于list1= 1,list2=2,list3=3..这样的语句,使代码显得更加简洁。

首先简单说一说exec(),exec()是一个十分有趣且实用的内置函数,不同于eval()函数只能执行计算数学表达式的结果的功能,exec()能够动态地执行复杂的Python代码,功能强大但是也有不少小地方容易踩坑的,坑好出但是不太好理解,光影并存吧。

动态执行简单的字符串代码

动态执行较复杂的代码

func = "def fact(n):\n\treturn 1 if n==1 else n*fact(n-1)"
exec(func)
a = fact(5)
print(a)

执行文件中的Python代码

在eg.txt中存储我们想放的Python代码

def fact(n):
    if n==1:
        return 1
    else:
        return n*fact(n-1)
t = fact(6)
print(t)

在exec中传参

x = 10
expr = """
z = 30
sum = x + y + z
print(sum)
"""

def func():
    y = 20
    exec(expr)
    exec(expr, {'x': 1, 'y': 2})
    exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4})

func()

使用中遇到的问题

今天在使用时遇到了一些问题简单记录一下。

def main():
    file_list = [2014, 2045, 2065, 2070, 2080, 2110, 2123, 2133]
    generate_outliers_analysis_log(file_list, "log/outliers.log")

    for file in file_list:
        csv_df = csv_file_to_df(r"D:/FTPD/newEnv/" + str(file) + ".csv")
        port_suffix = [33, 35, 36, 37, 39, 40]
        loc = locals()
        for suffix in port_suffix:
            # 通过执行字符串代码来避免反复执行相同语句
            exec("sorted_df_%s =  get_sorted_port_df(csv_df, '25GE1/0/%s')" % (str(suffix), str(suffix)))
        sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]
        sorted_df_37, sorted_df_39, sorted_df_40 = loc["sorted_df_37"], loc["sorted_df_39"], loc["sorted_df_40"]
        sorted_df_list = [sorted_df_33, sorted_df_35, sorted_df_36, sorted_df_37, sorted_df_39, sorted_df_40]
        name_list = ["25GE1/0/33", "25GE1/0/35", "25GE1/0/36", "25GE1/0/37", "25GE1/0/39", "25GE1/0/40"]
        save_port_figure_and_excel(range(1, 7), sorted_df_list, name_list, str(file), 'port_csv/' + str(file) + '.xlsx')

这一行代码在运行时遇到了报错:

sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]

报错信息如下:

sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]
KeyError: 'sorted_df_33'。

一看就让人觉得奇怪,为了避免出现KeyError的问题,exec常常和locals()连用。

首先,关于locals,个人认为值得注意的有四点:

  • 1.locals() 字典是局部命名空间的代理,它会采集局部作用域的变量,代码运行期若动态修改局部变量,只会影响该字典,并不会影响真正的局部作用域的变量。
  • 2.当再次调用 locals() 时(即两次调用locals()时),由于重新采集,则动态(exec())修改的内容会被丢弃,locals()会被刷新为不包含之前exec()执行后的kv对的字典。
  • 3.运行期的局部命名空间不可改变,这意味着 exec() 函数中的变量赋值不会对它产生影响,但 locals() 字典是可变的,会受到 exec() 函数的影响
  • 4.locals()字典既然是局部命名空间(字典)的代理,会包含在当前局部作用域中的所有的局部变量,那么在把locals()的结果赋给一个变量时,就会产生循环引用

第4点什么意思呢,举个简单的例子

def test():
    a = 13
    loc = locals()
    exec('b = a + 1')
    b = loc['b']
    print(b)

在上面这一小段代码中,当执行到loc = locals()这一行时,loc这一个字典会有一个key为‘loc’,值为loc这个字典本身的键值对。

而且这个loc是一个循环引用,看一下下面的debug图就知道了。为什么呢,因为locals()会包含在当前局部作用域中的所有的局部变量。由于loc本身也是一个局部变量,所以就造成了循环引用

exec的常见陷阱

https://segmentfault.com/a/1190000019217209

对遇到的问题的分析

看完上面的链接文章,个人觉得已经讲解的很透彻了。回头来简单看下,就是说对于下面的例一,会报一个KeyError,对于下面的例二,则不会报错。这与locals()的调用位置有关系,locals()是局部变量的字典的copy,运行期的局部命名空间(局部变量字典)不可改变,这意味着 exec() 函数中的变量赋值不会对它产生影响,但 locals() 字典是可变的,会受到 exec() 函数的影响。意味着我们如果希望在后面获取exec中动态执行的值来赋给新的变量的话,需要在exec之前调用locals(),否则无法获取

好,在此基础上我们来回顾今天遇到的问题,首先简化出现如上问题的业务代码为下图示例3的exec+locals+占位符的example3的使用方式,然后利用example4的方式来做一个简单的验证。咦,这里就出现了一个有趣的问题,按理来说,在example3()函数中,第2行定义了loc,这里的loc在第3行第4行执行完成后是会被exec修改的,即loc中是肯定有“a0”"a1"“a2”“a3”"a4"5个key的,这个在example4中也得到了验证,即只要不用原本的变量名就可以获取。我也不太明白为什么会产生这样的报错,也许这是exec和占位符的设计问题吧,由此也可以得出一个结论,在代码中要获取exec动态执行的变量值,建议还是不要重名,避免定位这些细小琐碎的问题花费较多的时间。:

参考

https://segmentfault.com/a/1190000014581721

https://segmentfault.com/a/1190000019217209

https://python3-cookbook.readthedocs.io/zh_CN/latest/c09/p23_executing_code_with_local_side_effects.html

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python的exec 的相关文章

  • API 端点的 Django 子域配置

    我已经建立了一个 Django 项目 它使用django rest framework提供一些 ReST 功能 网站和其他功能都运行良好 然而有一个小问题 我需要我的 API 端点指向一个不同的子域 例如 当用户访问该网站时 他 她可以根据
  • 操作数无法与形状 (128,) (0,) 错误一起广播

    我正在尝试实现面部识别登录系统 但出现错误 操作数无法与形状 128 0 一起广播 我不知道什么或如何解决它 这是我已实现的 view py 和 FaceDetector py 以及我从服务器收到的错误 errors Traceback m
  • PyList_SetItem 与 PyList_SETITEM

    据我所知 PyList SetItem 和 PyList SETITEM 之间的区别在于 PyList SetItem 会降低它覆盖的列表项的引用计数 而 PyList SETITEM 不会 我有什么理由不应该一直使用 PyList Set
  • DataFrame 在函数内部修改

    我面临一个我以前从未观察到的函数内数据帧修改的问题 有没有一种方法可以处理这个问题 以便初始数据帧不被修改 def test df df tt np nan return df dff pd DataFrame data 现在 当我打印时d
  • Spark MLlib - 训练隐式警告

    我在使用时不断看到这些警告trainImplicit WARN TaskSetManager Stage 246 contains a task of very large size 208 KB The maximum recommend
  • Python 在 chroot 中运行时出现错误

    我尝试在 chroot 中运行一些 Python 程序 但出现以下错误 Could not find platform independent libraries
  • Python sqlite3游标没有属性commit

    当我运行这段代码时 path Scripts wallpapers single png conn sqlite3 connect Users Heaven Library Application Support Dock desktopp
  • html 解析器 python

    我正在尝试解析一个网站 我正在使用 HTMLParser 模块 问题是我想解析第一个 a href 评论后 但我真的不知道该怎么做 所以我在文档中发现有一个函数叫做handle comment 但我还没有找到如何正确使用它 我有以下内容 i
  • 为 Networkx 图添加标题?

    我希望我的代码创建一个带有标题的图 使用下面的代码 可以创建绘图 但没有标题 有人可以告诉我我做错了什么吗 import pandas as pd import networkx as nx from networkx algorithms
  • 在Python中删除带有重音符号的字符串中的所有非字母字符

    我正在尝试使用 Python 3 7 从包含重音符号的字符串中删除所有非字母字符 空格除外 我尝试了以下方法 import re text 29 1981 4 2008 clean text re sub W d text print cl
  • Python 视频框架

    我正在寻找一个 Python 框架 它将使我能够播放视频并在该视频上绘图 用于标记目的 我尝试过 Pyglet 但这似乎效果不是特别好 在现有视频上绘图时 会出现闪烁 即使使用双缓冲和所有这些好东西 而且似乎没有办法在每帧回调期间获取视频中
  • 如何检查列表是否为空?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 例如 如果通过以下内容 a 我如何检查是否a是空的 if not a print Lis
  • 如何在 Python 中从 HTML 页面中提取 URL [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我必须用Python 编写一个网络爬
  • 如何强制 Y 轴仅使用整数

    我正在使用 matplotlib pyplot 模块绘制直方图 我想知道如何强制 y 轴标签仅显示整数 例如 0 1 2 3 等 而不显示小数 例如 0 0 5 1 1 5 2 等 我正在查看指导说明并怀疑答案就在附近matplotlib
  • 如何向 SCons 构建添加预处理和后处理操作?

    我正在尝试在使用 SCons 构建项目时添加预处理和后处理操作 SConstruct 和 SConscript 文件位于项目的顶部 预处理动作 生成代码 通过调用不同的工具 gt 不知道在此预处理之后将生成的确切文件 可以创建用于决定生成哪
  • 从另一个 python 脚本获取返回信息

    我在 Linux 上 我有一个 python 脚本 我想从另一个 python 脚本调用它 我不想将其作为模块导入 为了一层安全性 现在为了学术练习 因为我想弄清楚这一点 我实际上想让一个脚本使用 os system 或另一个类似的函数 并
  • 最小硬币找零问题——回溯

    我正在尝试用最少数量的硬币解决硬币找零问题 采用回溯法 我实际上已经完成了它 但我想添加一些选项 按其单位打印硬币数量 而不仅仅是总数 这是我下面的Python代码 def minimum coins coin list change mi
  • scipysolve_ivp() 中的访问时间步长

    我有一个常微分方程系统 正在使用 scipy 的solve ivp 函数求解 它运行良好 但我在访问每个步骤中使用的时间步时遇到问题 我知道solve ivp 将当前时间传递给用户定义的函数 但我需要使用的时间步长 而不是当前时间 为了解决
  • Python 枚举子集迭代

    我想迭代以下枚举的子集 class Items enum Enum item1 0 item2 1 item3 2 item4 3 item5 4 item6 5 item7 6 item8 7 说我想 for item in Items
  • 为什么用字符串和时间增量转置 DataFrame 会转换数据类型?

    这种行为对我来说似乎很奇怪 id列 字符串 在转置后转换为时间戳df如果另一列是时间增量 import pandas as pd df pd DataFrame id 00115 01222 32333 val 12 14 170 df v

随机推荐

  • 【计算机毕业设计】232流浪动物领养信息系统

    一 系统截图 需要演示视频可以私聊 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术 让传统数据信息的管理升级为软件存储 归纳 集中处理数据信息的管理方式 本流浪动物领养信息系统就是在这样的大环境下诞生 其可以帮助管理者在短时间内处理
  • Windows、Linux中std::this_thread::get_id()导致的Qt中sql执行报Driver not loaded错误

    Windows Linux中std this thread get id 导致的Qt中sql执行报Driver not loaded错误 抽象代码 void dosomework std ostringstream oss oss lt l
  • QTcpSocket 发送数据的几种方法

    1 QTcpSocket 继承于QAbstractSocket继承于QIODevice 2 QTcpSocket 提供的几种接收和发送数据方法 write const char qint64 qint64 write const char
  • 一百、Kettle(9.3.0)连接ClickHouse

    注意 低版本的kettle即使装ClickHouse驱动包后也不一定支持ClickHouse数据库连接 具体kettle从什么版本开始支持ClickHouse没测试过 只有高版本的kettle在安装ClickHouse驱动包后才支持Clic
  • 关于Winsows安装baselines的问题

    关于Winsows安装baselines的问题 windows是否可以使用baselines 根据GitHub上关于baselines的介绍 只有Linux和MAC OS给了配置说明 用pip在windows上安装的baselines只有最
  • HTML获取当前选中的li标签

    获取该class下的li标签 layui tab title li click function li标签下标默认为0 var liindex this index
  • foreach跳出本次/当前循环与终止循环方法及switch跳出方法

    目录 1 普通for循环 2 java中的foreach循环 3 js中的foreach循环 4 switch 1 普通for循环 continue 当满足某个条件时 想要跳出本次循环继续执行下次循环 break 满足某个条件的时候 终止f
  • 遗传算法优化BP神经网络的原理是什么

    遗传算法优化BP神经网络的原理是通过进行大量重复的试验 使用遗传算法来改进和优化神经网络的参数 以使神经网络能够更好地完成特定任务 遗传算法通过进化算法对神经网络中的参数进行重新调整 从而获得更好的性能
  • SQL中的CASE WHEN使用 .

    Case具有两种格式 简单Case函数和Case搜索函数 简单Case函数 CASE sex WHEN 1 THEN 男 WHEN 2 THEN 女 ELSE 其他 END Case搜索函数 CASE WHEN sex 1 THEN 男 W
  • 萤石摄像头RTSP流获取(黑屏解决)

    前言 在获取萤石摄像头RTSP视频流时 视频流获取不成功 黑屏并且一直显示缓冲中 下面对获取过程中查阅的资料和解决方案做一下汇总 打开RTSP 在萤石云视频APP中打开RTSP 我的 工具 局域网设备预览 开始扫描 选择摄像头 设置 更多设
  • 本地代码上传github

    怎么将新创建的本地代码上传到github上 这里简单的记录一下 我喜欢使用命令行 这里全用命令行来实现 不了解git命令的可以去了解下 1 先在github中创建仓库 2 回到你本地项目路径下右击打开git 没有的自行安装即可 3 初始化
  • ios.js?v=7c33aa19:1183 Uncaught (in promise) AxiosError {message: ‘Request failed with status code 4

    ios js v 7c33aa19 1183 Uncaught in promise AxiosError message Request failed with status code 404 name AxiosError code E
  • mysql中 or的使用方法,mysql条件查询中与or同时使用时的注意事项!!

    我们在日常的crud开发中 经常会遇到查询数据不是预期效果的问题 但是有感觉自己的查询语句没什么问题呀 怎么会出错呢 今天我也中招了 就很烦 sql如下 在查询语句中我们有一个条件是year 2021 但是查询结果还包含了2020的数据 这
  • Windows WSL配置ubuntu环境并登录

    一 什么是WSL wsl即适用于Windows的Linux子系统 Windows subsystem for Linux 二 Windows WSL配置ubuntu环境 1 管理员运行cmd 执行以下命令启用 适用于 Linux 的 Win
  • Codeforces Round 739 (Div. 3)

    A Dislike of Threes AC代码 include
  • Git的版本和分支管理

    1 http blog csdn net xiahouzuoxin article details 9393119 2 http blog csdn net xiahouzuoxin article details 9398629 3 ht
  • Qt在linux系统中执行shell命令

    在linux系统下 Qt执行shell命令的方式有3种 1 QProcess execute ls 2 system ls 3 QProcess process new QProcess process gt start ls 注1 以上3
  • 解决ubuntu20搜狗输入法输入不了中文问题

    解决在ubuntu上安装好搜狗输入法后无法输入中文 首先按照官网的安装步骤安装 Ubuntu搜狗输入法安装指南 注意不要忘记安装依赖 输以下命令进行安装 sudo apt install libqt5qml5 libqt5quick5 li
  • 接口测试的测试用例该怎么写呢?

    作者 字节开发测试 链接 https www zhihu com question 305629217 answer 2530044958 来源 知乎 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 一 什么是接口 接口
  • Python的exec

    目录 exec 简单使用 动态执行简单的字符串代码 动态执行较复杂的代码 执行文件中的Python代码 在exec中传参 使用中遇到的问题 参考 exec 简单使用 个人比较喜欢用Python里面的exec 可以用来动态执行字符串代码 在f