无法让 python subprocess.Popen() 在后台启动另一个 python 脚本

Can't get python subprocess.Popen() to start another python script in the background

我在这里有点困惑。我有一个 python 脚本 (gather.py),它从一个 .xml 文件中收集信息,并在休眠 60 秒的无限循环中将其上传到数据库中;顺便说一句,所有这些都是本地的。我正在使用 Flask 运行 一个稍后会从数据库中提取信息的网页,但目前它所做的只是显示一个示例页面 (main.py)。我想 运行 main.py 启动 gather.py 作为不会阻止 Flask 启动的后台进程,我尝试导入 gather.py 但它暂停了进程(无限期) 并且 Flask 不会启动。在谷歌搜索一段时间后,似乎最好的选择是使用任务队列(Celery)和消息代理(RabbitMQ)来处理这个问题。如果应用程序要在后台做很多事情,这很好,但我只需要它做 1 或 2 件事。所以我做了更多的挖掘,发现 posts 指出 subprocess.Popen() 可以完成这项工作。我尝试使用它,但我认为它没有失败,因为它没有引发任何错误,但数据库是空的。我确认 gather.py 和 main.py 都是独立工作的。我尝试 运行 在 IDLE 中使用以下代码:

subprocess.Popen([sys.executable, 'path\to\gather.py'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

并在 return 中得到了这个:

<subprocess.Popen object at 0x049A1CF0>

现在,我不知道这意味着什么,我尝试使用 .value.attrib,但可以理解我明白了:

AttributeError: 'Popen' object has no attribute 'value'AttributeError: 'Popen' object has no attribute 'attrib'

然后我在 Whosebug post 上读到 stdout=subprocess.PIPE 会导致程序停止,所以在 'just in case' 时刻,我 运行:

subprocess.Popen([sys.executable, 'path\to\gather.py'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)

并在 return 中得到了这个:

<subprocess.Popen object at 0x034A77D0>

在整个过程中,数据库表一直是空的。我是 subprocess 模块的新手,但所有这些检查,我无法弄清楚为什么它不是 运行ning gather.py。是因为它有一个无限循环吗?如果有更好的选择请告诉我。

Python版本:3.4.4

PS。 IDK 如果这很重要,但我正在 运行 在 Windows 10 PC 上安装 Python (PortableApps) 的便携式版本。这就是为什么我在 subprocess.Popen().

中包含 sys.executable

解决方案 1(全部在 python 脚本中): 尝试使用线程和队列。

我这样做:

from flask import Flask
from flask import request
import json

from Queue import Queue
from threading import Thread
import time


def task(q):
    q.put(0)
    t = time.time()
    while True:
        time.sleep(1)
        q.put(time.time() - t)
        

queue = Queue()
worker = Thread(target=task, args=(queue,))
worker.start()

app = Flask(__name__)


@app.route('/')
def message_from_queue():
    msg = "Running: calculate %f seconds" % queue.get()
    return msg

if __name__ == '__main__':
    app.run(host='0.0.0.0')

如果您 运行 此代码每次访问“/”都会在后台 task 中计算一个值。也许您需要阻塞直到任务获得值,但问题中的信息不足。当然,您需要重构 gather.py 以为其传递队列。

方案二(使用系统脚本):

对于 windows,从那里创建一个 .bat 文件和 运行 两个脚本:

@echo off
start python 'path\to\gather.py'
set FLASK_APP=app.py
flask run

这将 运行 gather.py 然后启动烧瓶服务器。如果您使用 start /min python 'path\to\gather.py',收集将 运行 处于最小化模式。

subprocess.Popen 无法打开 python 程序,因为它将 python 识别为文件而不是可执行文件。 Subprocess.Popen 只能打开.exe 文件,除此之外别无他法。 您可以使用:

os.system('python_file_path.py')

但它不会是后台进程(取决于您的脚本)