Python中subprocess.Popen执行报错求助(新手入门问题)
问题:Python subprocess.Popen报错:TypeError: 'NoneType' object is not iterable(办公启动脚本)
我是Python新手,刚完成一门YouTube上的Python入门课程,目前正在将办公用的启动批处理文件转为Python脚本作为首个项目。该脚本原本需要打开我办公时所需的所有应用程序,但编写的代码运行时出现报错。
我的代码如下:
import subprocess keys = [] open_now = "" count = 0 programs_to_run = {'Chrome': r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe', 'Outlook': r'C:\Program Files\Microsoft Office\\root\Office16\OUTLOOK.exe'} # 将字典中的键存入可用列表 for key in programs_to_run.keys(): # print(key) keys.append(key) for program in programs_to_run: open_now = "programs_to_run.get(programs_to_run.get(keys[count]))" subprocess.Popen(open_now) print(f'Opening {keys[count]}!') # print(programs_to_run.get(keys[count])) count += 1 print("*****************************************************************") print("All applications opened fine.") print("*****************************************************************") input('Press ENTER to exit') quit()
我曾在命令提示符中测试subprocess.Popen('完整路径'),运行正常,单独打印相关代码段也没问题,但运行上述完整代码时出现如下报错:
Traceback (most recent call last): File "C:/Users/User/OneDrive - Company/Python_Projects/WorkSetup/WorkSetup.py", line 28, in <module> subprocess.Popen(programs_to_run.get(programs_to_run.get(keys[count]))) File "C:\Users\User\AppData\Local\Programs\Python\Python38-32\lib\subprocess.py", line 854, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Users\User\AppData\Local\Programs\Python\Python38-32\lib\subprocess.py", line 1247, in _execute_child args = list2cmdline(args) File "C:\Users\User\AppData\Local\Programs\Python\Python38-32\lib\subprocess.py", line 549, in list2cmdline for arg in map(os.fsdecode, seq): TypeError: 'NoneType' object is not iterable
希望能得到入门级的帮助,我的最终目标是让该脚本/可执行文件随电脑启动,判断是否处于办公环境(本地域可达),若是则打开全部应用,否则仅打开2个应用(目前暂未实现该判断功能)。
解答
先说说报错的核心原因
你这段代码里绕了个没必要的弯,还犯了两个小错误:
- 你把
programs_to_run.get(...)写成了字符串赋值给open_now,就算去掉引号,programs_to_run.get(programs_to_run.get(keys[count]))也是错的——programs_to_run.get(keys[count])已经是程序的路径了,再拿这个路径当key去字典里找值,自然找不到,返回None,而subprocess.Popen接收到None就会报这个迭代错误。 - 手动维护
keys列表和count变量完全没必要,遍历字典有更简单的方式。
修正后的代码
import subprocess # 修正了Office路径的双斜杠(r前缀已经转义,单斜杠就够) programs_to_run = { 'Chrome': r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe', 'Outlook': r'C:\Program Files\Microsoft Office\root\Office16\OUTLOOK.exe' } # 直接遍历字典的键值对,不用额外维护列表和计数器 for app_name, app_path in programs_to_run.items(): try: # 用列表形式传路径是subprocess的最佳实践,避免路径含空格的问题 subprocess.Popen([app_path]) print(f'Opening {app_name}!') except Exception as e: # 捕获异常,就算某个程序启动失败也不影响其他程序 print(f'Failed to open {app_name}: {str(e)}') print("*****************************************************************") print("All applications opened (or attempted to open) fine.") print("*****************************************************************") input('Press ENTER to exit')
代码细节解释
- 更简洁的字典遍历:用
programs_to_run.items()可以直接拿到每个程序的名称和路径,省去手动存keys和计数的麻烦,代码更清晰不易出错。 - subprocess的正确用法:把路径放在列表里
[app_path]是官方推荐的写法,能避免路径里有空格时的解析问题,比直接传字符串更稳妥。 - 异常捕获:增加
try-except块后,就算某个程序路径写错或者权限不足,脚本也能继续启动其他程序,还能告诉你具体哪里出了问题。 - 路径修正:把Office路径里的
\\改成\,因为r开头的原始字符串中,单个\就代表路径分隔符,双斜杠会变成实际的两个斜杠,可能导致路径找不到。
后续域判断功能的入门思路
要判断是否在办公域,最入门的方法可以试试ping域服务器或者访问内网共享,这里给你一个ping的示例:
import subprocess def is_in_work_domain(): # 替换成你的域服务器IP或内网主机名 domain_server = "your-domain-server.local" # Windows下ping命令用-n指定次数,Linux/macOS用-c result = subprocess.run( ["ping", "-n", "1", domain_server], capture_output=True, text=True, # 隐藏命令窗口(Windows下生效) creationflags=subprocess.CREATE_NO_WINDOW ) # 返回码为0说明ping通了,代表在办公域 return result.returncode == 0 # 使用示例 if is_in_work_domain(): print("检测到办公环境,启动全部程序") # 这里放启动所有程序的代码 else: print("不在办公环境,启动常用程序") # 这里放启动2个指定程序的代码
把这段逻辑和之前的启动代码结合,就能实现你的最终需求啦。
内容的提问来源于stack exchange,提问作者DragonStar445




