欢迎光临
我们一直在努力

025、while 循环的正确姿势:死循环预防、哨兵模式、交互式菜单

025、while 循环的正确姿势:死循环预防、哨兵模式、交互式菜单

上周帮一个刚入行的同事排查线上问题,发现他的爬虫脚本跑了三天后把服务器CPU打满了。一看代码,一个while True循环里没有break条件,连个sleep都没有。这种问题在初学者代码里太常见了——while循环看似简单,但用不好就是一颗定时炸弹。

死循环:不是你想停就能停

先看一个典型的“翻车现场”:

# 别这样写!我见过有人把这段代码部署到生产环境
count = 0
while count < 10:
print("正在处理第", count, "个任务")
# 这里踩过坑:忘记更新计数器
# count += 1 # 注释掉这行,循环永远跑不完

这段代码会无限打印“正在处理第 0 个任务”。count永远等于0,条件永远为True。CPU会一直飙升,直到你手动kill进程或者服务器重启。

死循环的三种常见死法:

  • 忘记更新循环变量——上面那个例子就是典型
  • 条件永远为True——比如while 1:或者while True:却没有break
  • 逻辑错误导致条件无法满足——比如while x > 0:但x一直在增加
  • 我自己的经验是:写while循环时,先写退出条件,再写循环体。就像写代码前先想好怎么收尾一样。

    # 正确的姿势:先确认退出机制
    count = 0
    while count < 10:
    print("正在处理第", count, "个任务")
    count += 1 # 这里踩过坑,但这次记住了

    哨兵模式:让循环自己喊停

    哨兵模式是我最喜欢用的while循环写法。所谓哨兵,就是一个特殊值,当它出现时循环就结束。

    # 哨兵模式:用户输入'quit'时退出
    while True:
    user_input = input("请输入命令(输入quit退出):")
    if user_input == 'quit': # 'quit'就是哨兵
    print("收到退出指令,拜拜")
    break
    print("你输入了:", user_input)

    这个模式在处理文件读取时特别香:

    # 读取文件直到遇到空行(空行就是哨兵)
    with open('config.txt', 'r') as f:
    while True:
    line = f.readline()
    if not line: # 空字符串就是哨兵
    break
    print("配置项:", line.strip())

    哨兵模式的核心思想:用一个不可能出现在正常数据中的值作为终止信号。比如处理用户输入时用’quit’,处理数字时用-1,处理字符串时用空字符串。

    交互式菜单:while循环的实战场景

    命令行工具里最常见的场景就是交互式菜单。我写过不下20个这样的工具,每次都用同一个模板:

    def show_menu():
    print("\\n=== 系统管理工具 ===")
    print("1. 查看系统状态")
    print("2. 清理缓存")
    print("3. 重启服务")
    print("0. 退出")

    def main():
    while True:
    show_menu()
    choice = input("请选择操作:")

    if choice == '1':
    print("正在查看系统状态…")
    # 这里踩过坑:忘记加延时,导致CPU占用过高
    # time.sleep(0.1)
    elif choice == '2':
    print("正在清理缓存…")
    elif choice == '3':
    print("正在重启服务…")
    elif choice == '0':
    print("感谢使用,再见!")
    break
    else:
    print("无效选择,请重新输入")

    if __name__ == '__main__':
    main()

    这个模板我用了好几年,有几个关键点:

    • 菜单显示放在循环里:每次操作完都能看到菜单
    • 用break退出:而不是修改循环条件
    • 处理无效输入:防止用户乱按导致程序崩溃

    实战经验:while循环的五个铁律

  • 永远不要写裸的while True——至少加个sleep或者明确的break条件。我见过最离谱的代码是while True: pass,直接把CPU干到100%。

  • 哨兵值要选对——处理用户输入时,‘quit’、‘exit’、'q’都要考虑。处理数字时,-1或者0通常是不错的选择。

  • 循环体内要有延时——特别是轮询场景,比如检查文件是否生成、等待API响应。time.sleep(0.1)就能让CPU从100%降到1%。

  • 考虑超时机制——有些循环可能因为外部原因永远跑不完。加个超时计数器,超过一定次数就强制退出。

  • # 超时保护:防止死循环
    max_retries = 5
    retry_count = 0
    while retry_count < max_retries:
    try:
    result = api_call()
    if result:
    break
    except Exception as e:
    print(f"第{retry_count+1}次调用失败:{e}")
    retry_count += 1
    time.sleep(1)

  • 日志记录——生产环境里的while循环一定要加日志。不然出了问题你都不知道循环卡在哪一步。
  • 个人经验

    写while循环这么多年,最大的感悟是:循环越简单越好。复杂的业务逻辑不要塞进循环体,拆成函数。循环只负责“什么时候继续”和“什么时候停止”,具体做什么交给函数去处理。

    还有一个容易被忽视的点:while循环里的异常处理。如果循环体里抛了异常没捕获,整个循环就挂了。我习惯在循环体最外层加个try-except,至少保证异常不会让循环意外终止。

    最后说一句:能用for循环解决的问题,别用while。for循环天然有边界,while循环需要你自己维护边界。少一个变量就少一个bug源。

    赞(0)
    未经允许不得转载:171主机测评 » 025、while 循环的正确姿势:死循环预防、哨兵模式、交互式菜单
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址