一日一技:为什么exit()无法退出程序?

简介: 一日一技:为什么exit()无法退出程序?

我们在Python交互环境的里面,可能会使用exit()来退出程序,例如:


1.png


有时候,当我们想让Python程序在遇到某些条件的时候退出,也可以使用exit(),如下图所示:


def run(options):
    if options == '1':
        print('执行逻辑1')
    elif options == '2':
        print('执行逻辑2')
    elif options == 'exit':
        print('退出程序!')
        exit()
    else:
        print('只能输入1,2或者exit')
while True:
    option = input('请输入选项:')
    run(option)


2.png

但有时候,你会发现exit()似乎出了一些问题。执行它以后,程序虽然确实也会结束,但是它会报错。例如下面这段代码:


def run(options):
    if options == '1':
        print('执行逻辑1')
    elif options == '2':
        print('执行逻辑2')
    elif options == 'exit':
        print('退出程序!')
        exit()
    else:
        print('只能输入1,2或者exit')
while True:
    option = input('请输入选项:')
    try:
        run(option)
    except:
        pass


运行效果如下图所示:

image.gif

3.png


还有一些时候,exit()甚至直接失效,例如:


def func(param):
    def wrap(args):
        try:
            print(args)
            exit()
        except:
            pass
    wrap(param)
for i in range(10):
    func(i)


运行效果如下图所示。


4.png

要解释这个问题,我们就要先来搞清楚,在Python里面,退出当前程序的几个命令:exit()quit()sys.exit()os._exit()有什么区别和联系。


实际上,exit()quit()sys.exit(),他们背后的原理都是一样的,都是在执行的时候,抛出一个异常raise SystemExit。所以,我们甚至可以直接在代码里面手动抛出这个异常来退出程序:


5.png


在正常情况下,无论你是执行这三个命令,还是手动抛出SystemExit异常,Python解释器都能检查到这个异常,然后清理当前进程占用的各个句柄和缓存buffer。


但问题在于,SystemExit是基于BaseException实现的一个异常,所以当你的代码里面使用try...except...的时候,你会捕获到这个异常。但是在except里面,你又直接pass了,所以就什么也做不到。于是程序就无法正常退出了。


如果你非要使用try ... except ...其实也很简单,你使用具体的某个异常,或者直接使用Exception。这样一来,由于SystemExit不是基于Exception的,所以就不会被捕获。捕获了Exception以后,代码运行效果如下图所示:


6.png


从图中可以看到,程序打印了第一个数字就正常退出了。


上面的问题解决了,可能还有人会问,这四个退出方法有什么区别呢?其实exit()quit()完全一样,就是方便有些人习惯用exit这个词,有些人习惯用quit()这个词。一般来说,当你在Python互换环境里面,可以使用这两个函数的任何一个来退出。

sys.exit()需要提前导入sys模块。所以一般在.py项目代码里面使用。因为可能有些系统的Python环境,没有exit()quit()函数,但肯定有sys模块。


而至于os._exit()这个函数,它可以立刻结束当前进程,不会清理句柄,也不会清理缓存buffer。就相当于kill -9 进程ID


请关注微信公众号【未闻Code】获取更多精彩文章。

目录
相关文章
|
存储 SQL druid
什么是Druid
什么是Druid
5180 1
什么是Druid
|
Kubernetes API 计算机视觉
利用 member update 实现 etcd 灾难恢复 [也可实现 etcd 集群迁移]
利用 member update 实现 etcd 灾难恢复 [也可实现 etcd 集群迁移]
1469 0
|
传感器 JSON 监控
python中psutil模块的使用详解(python3经典编程案例)
这篇文章介绍了如何使用Python的`pyinstaller`库打包应用程序,并提供了详细的打包步骤和参数说明。
430 7
|
7月前
|
计算机视觉
YOLOv11改进策略【卷积层】| CVPR-2024 利用DynamicConv 动态卷积 结合C3k2进行二次创新,提高精度
YOLOv11改进策略【卷积层】| CVPR-2024 利用DynamicConv 动态卷积 结合C3k2进行二次创新,提高精度
551 0
|
存储 NoSQL 安全
保障安全与可扩展性:Redis安全设置与集群扩展
本篇深入探讨了Redis的安全性设置以及构建可扩展的Redis集群的方法。我们首先介绍了如何通过设置密码、禁用危险命令和限制访问来加强Redis的安全性。进一步地,我们讨论了如何进行访问控制和权限管理,以确保只有授权用户可以访问和操作Redis。
975 2
保障安全与可扩展性:Redis安全设置与集群扩展
|
数据采集 Python
如何用Python Selenium和WebDriver抓取LinkedIn数据并保存登录状态
本文介绍了使用Python Selenium和WebDriver库抓取LinkedIn数据的方法。首先,安装Selenium库和对应的WebDriver,然后配置爬虫代理IP以避免频繁请求被检测。接下来,设置user-agent和cookies以模拟真实用户行为,实现登录并保持状态。登录后,使用WebDriver抓取目标页面数据,如用户名、年龄、性别和简历信息。最后,强调了优化代码、处理异常和遵守使用条款的重要性,以提高效率并避免账号被封禁。
422 2
如何用Python Selenium和WebDriver抓取LinkedIn数据并保存登录状态
|
存储 NoSQL Java
Java中使用redis的bitMap实现签到功能
这个实现示例提供了一种灵活、高效的方式,展示了如何使用Redis来解决现实中的问题。
504 2
|
算法 数据可视化
使用SAS,Stata,HLM,R,SPSS和Mplus的分层线性模型HLM
使用SAS,Stata,HLM,R,SPSS和Mplus的分层线性模型HLM
|
分布式计算 Hadoop Java
centos 部署Hadoop-3.0-高性能集群(一)安装
centos 部署Hadoop-3.0-高性能集群(一)安装
347 0
|
消息中间件 监控 安全
探究如何在Linux系统中修改进程资源限制:四种方法调整进程限制,让你的系统高效运行(包含应用层getrlimit和setrlimit API)
探究如何在Linux系统中修改进程资源限制:四种方法调整进程限制,让你的系统高效运行(包含应用层getrlimit和setrlimit API)
2078 0