Python脚本如何调用cmd执行目录切换与批处理并等待执行完成
原实现的核心问题
你现在写的代码逻辑完全跑不通,根源是对subprocess.communicate()的运行机制理解有偏差:
- 单次调用
communicate()的设计逻辑就是:把传入的字节内容全部写入子进程的标准输入通道后,立刻关闭stdin连接,然后阻塞当前线程直到子进程完全退出。也就是说第一次传完cd命令,stdin就已经被彻底关掉了,cmd进程会直接收到输入结束的信号退出,根本走不到第二次调用run.bat的步骤。 - 就算绕开
communicate手动往stdin里写内容、手动flush,Windows的cmd批处理执行本身的流缓冲机制也经常出现“写进去的命令不被解析”的问题,调试成本极高,完全没必要走这条路。
适配你场景的正确实现方案
你要复现的“打开独立cmd窗口、进入目标工作目录、运行run.bat、等任务跑完自动关窗、再推进脚本后续流程”的逻辑,根本不需要手动拼接cd命令传给cmd,subprocess本身的参数就能100%复现你手动操作的环境:
Popen提供的cwd参数,是系统层直接给子进程设置启动时的工作目录,和你打开那个cmd快捷方式后进入的目录环境没有任何区别,能解决你之前直接调用bat失败的问题——很多bat依赖同目录的相对路径配置,这个参数设置后的运行环境和手动cd进去的环境完全一致。- 用
cmd /c <执行命令>的调用方式,cmd本身会在指定的工作目录下执行完命令后自动退出窗口,不需要手动发exit指令、手动关进程。 - 调用
process.wait()就能实现你要的等待逻辑:Python脚本会阻塞在这里,直到对应cmd窗口内的任务完全执行结束、窗口自动关闭后,才会继续往下走。
基础单任务示例代码
import subprocess # 替换成你那个cmd快捷方式对应的目标目录(就是run.bat所在的文件夹) target_dir = r"C:\你的run.bat所在的文件夹路径" # 替换成你手动在cmd里敲的执行命令 exec_command = "run.bat" # 启动独立的新cmd窗口 process = subprocess.Popen( f"cmd /c {exec_command}", cwd=target_dir, # 强制打开独立的控制台窗口,和你手动双击打开的cmd窗口效果一致 creationflags=subprocess.CREATE_NEW_CONSOLE ) # 阻塞等待当前cmd内的命令完全执行完成 process.wait() # 走到这里就说明run.bat已经跑完、cmd窗口已经自动关闭,可以继续推进后续逻辑
适配循环逻辑的写法
如果要逐次处理多个任务,只要把上面的启动逻辑套进循环即可:
# 替换成你的任务列表,每个元素包含对应任务的工作目录、要执行的命令 task_list = [ {"work_dir": r"C:\path1", "command": "run.bat"}, {"work_dir": r"C:\path2", "command": "run.bat"}, ] for task in task_list: proc = subprocess.Popen( f"cmd /c {task['command']}", cwd=task["work_dir"], creationflags=subprocess.CREATE_NEW_CONSOLE ) # 等当前任务的cmd完全跑完,再启动下一个 proc.wait()
补充说明
你之前提到直接调用bat跑不通,本质就是之前的调用没有把工作目录设置对,bat脚本内部的相对路径找不到对应的依赖文件。用
cwd参数设置后,启动的cmd环境和你手动靠快捷方式进入目录敲命令的环境完全一致,不会出现环境差异导致的执行失败问题。
内容的提问来源于stack exchange,提问作者Ellio
相关产品推荐
相关产品推荐

