☰
PyCharm如何同时运行多个程序?四种多开方案与配置技巧
2026/10/1 3:17:32 网站建设 项目流程

如果你在PyCharm里点完一个Run,紧接着去点另一个脚本,发现上一个程序莫名其妙被停了,恭喜你,你不是一个人——这个问题每隔几天就会在一些技术群里出现一次:“PyCharm是不是一次只能运行一个程序?”别急,答案是:PyCharm完全可以同时运行多个程序,而且有好几种玩法,只是默认设置看起来像“单程序模式”,把很多人给带偏了。这篇帖子我会从最底层的逻辑讲起,然后给出不同场景下的多开方案,最后带你把一套真实的“API服务+任务进程+报表任务”组合跑起来。不管你是刚照着安装教程装好IDE的新手,还是用了一两年的老用户,只要需要在本地同时跑服务、脚本和任务,这篇都值得存一下。

1. 为什么点一次Run,上一个程序就被“顶”掉了

1.1 先了解PyCharm默认做了什么

要理解这个现象,得先看PyCharm的运行机制。你写代码时点右上角绿色三角,或者右键菜单里的Run,实际启动的是一个叫“运行配置(Run Configuration)”的东西。它由三部分组成:哪一个脚本、用哪个解释器、带什么参数和环境变量。PyCharm的默认策略是:如果同一个运行配置已经处于运行状态,你又点了它,IDE会认为你想“重新启动”,于是先把旧的实例停掉,再启动一个全新的。这个行为在PyCharm里叫Rerun,看起来很智能,但也正是它让很多人以为“只能跑一个程序”。

但注意,这个“顶掉”只针对同一个配置。A配置在跑,你切换到B配置再Run,A不会退出。Run窗口(最底部的运行面板)里每个配置对应一个独立的Tab,切来切去互不影响。你可以做个小实验:先右键运行一个简单的a.py,随便写个while True加sleep;再运行b.py;切回Run窗口观察,两个Tab都在,a.py的输出还在一行一行滚。只要a.py没被手动停止,它一直活着。所以与其说“只能跑一个程序”,不如说PyCharm默认会帮你管理资源,避免同一个脚本被重复启动导致系统扛不住。

1.2 不是限制,是UI策略

如果看操作系统层面,就更清楚了。每次运行一个Python脚本,本质上是启动了一个独立的python解释器进程。你在终端里敲python a.py和在PyCharm里点Run,最终做的事情是一样的,都是创建一个新进程。PyCharm只是个工具,它不会从底层限制你只能创建一个Python进程。只要你愿意,你可以同时创建几十个进程,机器扛不扛得住另说。PyCharm做的只是界面层的工作:把每个进程的标准输出、错误输出收集到右侧的Run窗口里。

打个比方,这就像同一个文件管理器里可以同时打开多个窗口。文件管理器默认并不会因为你新开一个窗口就把之前的窗口全关了,但如果某个窗口自己提供了“重新打开并覆盖”的菜单项,那只是这个菜单项的行为,不代表文件管理器只支持一个窗口。PyCharm的Rerun策略就是这样一个覆盖行为。识别了这一点,“只能跑一个”的错觉就会彻底消失。

2. 同时运行多个程序的4种办法,由浅入深

2.1 不同脚本并行:右键Run就是最朴素的办法

最朴素也最好用的方案,就是让不同脚本使用不同的运行配置,逐个启动。PyCharm对每个脚本右键Run时,会自动为你创建一个以脚本文件名命名的配置。所以你只需要在项目里把两个脚本分别右键运行,PyCharm自动建好配置并各自启动。以后就算你想在A脚本运行期间重跑B脚本,直接切到B配置再点Run,A不会受任何影响。

具体操作流程是这样的:

  1. 在项目窗口中,右键第一个脚本,选择 Run 'xxx',或者直接打开脚本后点右上角的运行按钮。
  2. 用同样方法运行第二个脚本、第三个脚本。
  3. 把鼠标移动到底部Run窗口上方,会看到多个Tab,点击任意Tab查看对应进程的输出。
  4. 需要停止某一个时,先激活对应Tab,再点左上角红色方块Stop。

这个方法适合什么情况?最常见的场景是本地联调:你既要跑一个API服务,又要跑一个数据处理脚本,还要起一个定时任务。三个模块是同一个项目的不同部分,但它们依赖彼此在线,必须同时活着。用这种方式,每个模块都有自己的输出窗口,日志互不干扰,排查问题也方便。

2.2 同一个脚本多开:先勾选 Allow parallel run

同一脚本多开,情况就有点不一样了。比如你要测试同一个爬虫脚本并发跑5个实例时的表现,或者想让同一个服务脚本监听两个不同的端口。这时候,脚本是同一个,但实例需要多个。默认情况下PyCharm会用旧的把新的顶掉,所以要动手改一下配置。

进入 Run > Edit Configurations...,左侧选中对应配置,在 Execution 或者 General 区域找到 Allow parallel run,把它勾上。保存后,再运行同一个配置,PyCharm就不再停旧实例,而是直接新起一个并排的Tab。这个开关就是为“同脚本多实例并行”准备的。

如果不想动这个选项,还有一招是复制配置。在Edit Configurations里右键某个配置选择Duplicate,复制出来的配置名会带copy后缀。你只要改个名字,比如server_9001、server_9002,然后分别设置不同的端口环境变量,再逐个运行就行。复制配置本质上就是新建了一个独立的“说明书”,PyCharm会把它们完全当成两个不同的程序来管理。我实际用下来更喜欢复制,因为Tab名称一眼就能区分,不同实例之间不会混淆。

注意:Allow parallel run 是一个配置级别的开关。如果业务上确实不需要多实例,别随手全勾上,否则一键重跑很容易开出一堆进程,IDE反应变慢、日志满天飞,反而得不偿失。

2.3 代码内部编排:subprocess 和 multiprocessing

把多进程管理下沉到代码里,适合任务型场景。如果“多个程序”只是同一个业务系统里需要并行处理的子任务,没必要在IDE上开一堆Tab,直接在代码里用subprocess或multiprocessing把进程拉起来更可控。

先看subprocess,它适合从主程序里把其他脚本当独立服务拉起来:

import subprocess # 同时启动两个脚本,Popen不会阻塞主程序 p1 = subprocess.Popen(["python", "server.py"]) p2 = subprocess.Popen(["python", "worker.py"]) print("两个子进程已启动,主程序继续执行") # 需要结束时可以 p1.terminate()、p2.terminate()

再看multiprocessing,它适合同一个程序里并行跑多个带任务的函数,进程之间是真正并行,而不是线程切换出来的“并发”效果:

import multiprocessing import time def worker(name): for i in range(5): print(f"{name} 正在处理第 {i + 1} 条数据") time.sleep(1) if __name__ == "__main__": tasks = ["任务A", "任务B", "任务C"] processes = [] for t in tasks: p = multiprocessing.Process(target=worker, args=(t,)) p.start() processes.append(p) for p in processes: p.join()

注意Windows下multiprocessing代码必须放在ifname== 'main'保护块里。原因是Windows创建子进程时会重新导入主模块,如果不加保护,子进程会再次执行“启动子进程”的代码,很快引发递归错误,进程数直接爆炸。这个坑我后面还会细说。subprocess.Popen在这个场景里不用保护,因为它是直接拉起外部脚本,不涉及重新导入当前文件。

2.4 一键启动多个程序:Compound 复合配置

最后推荐一个很多人没用过的特性:Compound复合配置。它的作用是把多个已存在的运行配置打包成一个,一次点击全部启动。配置路径:Run > Edit Configurations... > 左上角+号 > Compound,然后在右侧把之前创建好的配置加入列表。保存后运行这个复合配置,列表里的配置会分别在各自的Run Tab里启动,效果等于你手动挨个点了多次Run,但省去了切换和记忆顺序的功夫。

它适合搭建本地开发环境。比如我的一个项目里,后端API、任务消费进程和前端构建脚本经常要一起跑,单独记忆三个配置的启动顺序很容易漏。做成一个Compound之后,每天开工只要点一次运行,三个进程一起上来。

不过它有个局限:只是“同时启动”,不关心配置之间的依赖关系,也不会等某个服务就绪再启动下一个。如果A服务没起来,B服务启动时去请求A服务,日志会直接报错,你得自己决定要不要按顺序启动,或者在代码里做重试。它不是docker-compose,不会帮你管编排,这一点要有预期。

3. 运行配置里这几个关键设置,决定你能不能优雅多开

3.1 一份配置字段对照表

多开能不能跑得顺,很大程度上取决于运行配置里几个字段填得对不对。我整理了一份对照,给你按图索骥:

设置项位置作用多开时的建议
Allow parallel runExecution 区域(不同版本可能叫General)控制同一配置能否同时跑多个实例并发测试或同脚本多实例时需要勾选
Script parametersScript 路径下面的参数框在启动时向脚本传入命令行参数,代码里通过sys.argv读取用它传实例编号、输入文件,避免硬编码
Environment variablesEnvironment 区域注入环境变量,代码通过os.environ读取多实例时用它区分端口、实例ID、日志路径
Working directoryEnvironment 区域指定进程工作目录,影响相对路径统一设为项目根目录或数据目录,否则相对路径经常报FileNotFoundError
Python interpreterPython 解释器区域决定用哪个解释器运行代码尽量统一用项目虚拟环境,避免不同实例依赖不一致

这五个字段里,多开场景下最容易出问题的其实是Working directory和Environment variables。很多人把脚本放在子目录,默认的工作目录却是项目根目录,代码里用相对路径读配置就会失败;多实例同跑时,如果不通过环境变量区分端口,第二个实例启动就会直接报“端口已占用”。这些坑如果你看过这张表再配置,基本能避开。

3.2 命名规范和配置管理

多开之后,你马上会发现一个新的问题:Run窗口的Tab越来越多,分不清谁是谁。PyCharm的Tab名称默认跟随配置名,所以配置命名直接决定了你的识别效率。我的建议是采用“脚本名_用途_端口/实例号”的结构,比如server_api_9001、worker_consumer_02、report_task_A。这样哪怕同时开着六七个Tab,一眼扫过去就知道哪个对应哪个。

配置的复制和删除也很常用。在Edit Configurations里选中某个配置,右键可以Duplicate,复制出来的配置继承原参数,只需要微调名称和环境变量就能快速产生一个变体,不用重新填一堆字段。删除配置也不用担心,配置只是PyCharm用来记录“怎么运行这个文件”的说明书,删除它并不会影响到实际的.py脚本文件。如果你希望所有新配置默认带一些公共环境变量,可以看看自己的PyCharm版本里有没有对应的Default/Python配置模板,直接修改模板,以后新建配置就自动带上了。找不到模板也不用费劲,偷懒的做法是复制一个已有配置再改,效果一样。

4. 实操实录:一台机器同时跑API服务、任务进程和报表任务

4.1 场景设定:为什么需要三个程序同时跑

光讲理论还是不够直观,我拿一个实际场景带大家走一遍完整流程。假设我手头有个小项目,需要同时跑三个角色:一个API服务对外提供数据、一个任务进程定时检查服务状态、一个报表进程定期打印运行统计。这三个角色彼此独立,但又属于同一套业务流程,只有全部在线才能把整个链路跑通。

先准备三个脚本。第一个是server.py,用Flask起一个最简API服务:

from flask import Flask, jsonify import os app = Flask(__name__) port = int(os.environ.get("APP_PORT", "9001")) @app.route("/health") def health(): return jsonify({"status": "ok", "port": port}) if __name__ == "__main__": app.run(host="127.0.0.1", port=port)

第二个是worker.py,它每隔几秒去请求一次上面那个服务的健康检查接口:

import time import requests url = "http://127.0.0.1:9001/health" while True: try: r = requests.get(url, timeout=3) print(f"worker 检查服务状态:HTTP {r.status_code}") except Exception as e: print(f"worker 检查服务异常:{e}") time.sleep(3)

第三个是report.py,它定期打印一条运行统计日志,并且通过环境变量RUN_ID区分实例:

import time import os from datetime import datetime run_id = os.environ.get("RUN_ID", "1") while True: now = datetime.now().strftime("%H:%M:%S") print(f"[report-{run_id}] {now} 统计任务运行中") time.sleep(5)

这里要注意,运行前记得先装依赖,三个脚本用到的库一共就两个:Flask和requests。直接pip install flask requests就行。端口我用9001,避开常见的8000和5000,减少被本地其他服务占用的概率。

4.2 配置与启动的完整过程

接下来打开Run > Edit Configurations...,点左上角+号,新建三个Python配置,分别命名为API_Service、Task_Worker、Report_Task,Script paths分别指向上面三个脚本。

第一步,在API_Service配置里找到Environment variables,填入APP_PORT=9001。这样代码里的os.environ.get("APP_PORT", "9001")就能读到9001这个值,如果你有第二个API实例,就可以把环境变量改成9002,代码一行都不用动。

第二步,在Report_Task配置里,Environment variables填RUN_ID=1。Task_Worker这一版暂时不需要特殊环境变量,因为它在代码里写死了访问9001端口。

第三步,依次运行。先选中API_Service,点运行按钮,它会启动Flask服务并显示监听9001端口的日志;再选择Task_Worker运行,worker会开始每隔3秒打印一次HTTP状态码;最后选择Report_Task运行,三个程序同时在线。这时候切到Run窗口,你会看到三个Tab,输出互不干扰。

第四步,为了演示同脚本多开,我们把Report_Task配置右键复制一份,名字改成Report_Task_2,Environment variables改成RUN_ID=2。运行这个新配置后,Run窗口会出现第四个Tab,两个报表进程同时输出,但每条日志前缀分别是report-1和report-2,一眼就能区分。

这时候顺便验证一下前面说的“顶掉”逻辑:如果在Report_Task运行期间,你再直接运行Report_Task,没勾Allow parallel run的话,旧的report-1实例就会被顶掉,而API_Service和Task_Worker完全不受影响。这个实验做完,你对PyCharm的并行机制应该就有很直观的感受了。

4.3 并行调试和资源占用观察

如果你在某个实例里发现了bug,可以改用Debug按钮而不是Run按钮。PyCharm支持同时挂多个调试会话,Debug窗口同样按Tab区分。你可以先Debug API_Service,再Debug Task_Worker,两个调试会话都在。切换断点时,要先确认当前激活的是哪个Tab,因为断点命中的会话会自动弹出对应Tab,如果是另一个会话的断点,看起来就像“乱跳”,其实只是IDE在帮你定位。

资源观察方面,运行三个进程后,打开任务管理器(Windows)或活动监视器(macOS),你会看到多个python进程同时存在。PyCharm只是其中几个进程的“宿主”和管理面板,真正干活的是这些系统进程。如果机器明显变卡,优先停掉不重要的Tab,或者给负载高的任务想办法优化。本机多开的基本盘就是这样:机器配置高就多开,配置一般就克制一点。

提示:PyCharm的Stop按钮只停止当前激活的那个会话,不是一键停全部。想批量关闭时可以右键Run窗口里的某个Tab,选Close,或者从运行配置下拉框里逐个Stop。别以为点一下红色方块所有程序都退了,这是很多人多开之后的第一个误操作。

5. 高频问题排查表和踩坑笔记

5.1 高频问题排查表

多开时你会碰到的麻烦,基本就集中在下面这张表里。我按“现象、原因、解决方案”三个维度整理,遇到问题照着查:

现象原因解决方案
再次运行同一个脚本时,旧的立刻退出同一配置默认Rerun,会先停旧再启新勾选Allow parallel run,或复制配置用不同名称
新起的程序报端口被占用两个实例用了同一个端口用Environment variables给每个实例不同端口,比如APP_PORT=9001、9002
多个实例输出相似,分不清谁是谁Tab名相同或日志没带标识配置名改清晰;代码里打印实例ID;用logging而不是print
程序明明停止,但端口还占着进程可能没被真正kill,或还有子进程残留在任务管理器/活动监视器里找到对应python进程结束,检查Compound里是否有遗留子进程
断点总是同时命中多个实例所有并行实例共享同一个断点设置条件断点,或先停掉不需要调试的会话
运行多个程序后电脑卡顿严重进程多、内存或CPU超载减少并行数量;用虚拟环境避免依赖混乱;及时停掉空闲Tab

前两条最常出现。尤其是端口占用,多开服务型程序时几乎一定遇到,只要你给每个实例分配不同环境变量就能解决。日志识别问题也常见,但只要配置命名规范、打印带实例标识,基本就根治了。

5.2 几个值得记住的实战教训

第一个教训来自multiprocessing和Windows的组合。我在Windows下写过一段很简单的并行任务脚本,忘了加ifname== 'main',然后在PyCharm里一运行,进程数像裂变一样疯涨,几秒内从1个涨到30多个,只能去任务管理器一个个结束。后来在Linux下试,同样的代码没事,但Windows的spawn机制就是这样:子进程会重新导入主脚本,没保护就会无限递归。这个锅不是PyCharm的,但多程序并行时最容易碰上,建议你把它写进自己的checklist。

第二个教训是日志问题。多开几个程序之后,如果大家共用同一个日志文件,或者只靠print输出到各自的Run Tab,排查问题时很难把因果关系串起来。我的经验是每个实例至少打印出“我是谁”标识:配置名也好、RUN_ID也好、进程PID也好,总能帮你快速定位。更进一步,给每个实例设置独立的日志文件,比如report-1.log、report-2.log,谁出了问题就翻谁的日志,省去从头到尾扫控制台的痛苦。

第三个教训是关于停止会话。刚多开那会儿,我总以为Stop按钮是全停,结果好几次点了Stop,其他程序还在默默跑,任务该执行完还在执行完。后来养成习惯:停之前先看激活的Tab是不是目标进程,再动手。同时开多了就定期在Run窗口清理一下,把已经运行完毕的灰色Tab关掉,保持工作区整洁,不然几十个Tab堆在那里,光找位置都费眼神。

现在我自己开PyCharm干活,默认就不只开一个运行Tab,服务、任务、脚本经常同时挂着。刚开始多开那阵子我也踩过不少坑,最典型的就是在Windows下跑multiprocessing忘了加main保护,眼看进程数一路涨到好几十,只能一个个去任务管理器里结束。后来养成了习惯:每个配置复制一份、环境变量区分实例、日志带标识,多开就再也不会乱了。你也不用一次性掌握全部技巧,先从今天第一个方案试起,把多个脚本同时跑起来,感受一下就回不去了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询