Es funktioniert nicht wie es sollte. Nicht ein einziges Mal. Es scheint so zu sein, dass es funktioniert, aber die Web-Anwendung garantiert nicht einmal einen einzelnen Thread, nicht einmal einen einzigen Prozess. Daher kann die Stoppanforderung von einem anderen Thread oder sogar einem anderen Prozess als der Startanforderung behandelt werden.
Sie können nicht erwarten, dass ein Wert aus einer Anfrage in einer anderen Anfrage verfügbar ist, es sei denn, Sie haben diese explizit beibehalten. In einem Cookie oder einer Datenbank. Eine Process
Instanz kann nicht auf diese Weise beibehalten werden, da ein Teil ihres Werts ein Prozess auf Betriebssystemebene ist. Sie könnten ihre Prozess-ID und möglicherweise ihre Elternprozess-ID speichern, um sicher zu sein, dass dieses Paar bei der Stoppanforderung erkannt wird. Hier ist ein Beispiel dafür, wie ein Session-Cookie für diesen Einsatz:
from multiprocessing import Process
from time import sleep
import psutil
from flask import Flask, redirect, session, url_for
app = Flask(__name__)
app.secret_key = 'f\xa9\x85\xf0\xe9\x982\xc4\xf8\xa0k\x91\xa7\xef\x12y'
@app.route('/')
def index():
return (
'<form action="/work/start" method="POST">'
'<input type="submit" value="Start">'
'</form>'
'<form action="/work/stop" method="POST">'
'<input type="submit" value="Stop">'
'</form>'
)
def work_it():
while True:
print('working...')
sleep(1)
@app.route('/work/start', methods=['POST'])
def start_work():
if 'work_process' not in session:
process = Process(target=work_it)
process.start()
pid = process.pid
parent_pid = psutil.Process(process.pid).parent().pid
session['work_process'] = (parent_pid, pid)
return redirect(url_for('index'))
@app.route('/work/stop', methods=['POST'])
def stop_work():
if 'work_process' in session:
parent_pid, pid = session['work_process']
try:
process = psutil.Process(pid)
if process.parent().pid == parent_pid:
process.terminate()
except psutil.NoSuchProcess:
pass
session.pop('work_process')
return redirect(url_for('index'))
Es nutzt psutil die Eltern Prozesse PID zu erhalten und den Prozess zu beenden.
Diese "Lösung" weist einige Mängel auf. Sie können einen Prozess per Browser oder sogar mehrere aus demselben Browser starten, wenn der Browser es erlaubt, die Cookies von verschiedenen Tabs/Fenstern zu trennen. Firefox tut dies mit der privaten Fensterfunktion. Und um einen Prozess zu stoppen, wird der Cookie benötigt. Wenn Sie also Cookies blockieren oder löschen, ist es nicht mehr möglich, den Vorgang mit der Schaltfläche Stop zu stoppen. Wieder Firefox als Beispiel: Wenn Sie ein privates Fenster schließen, sind seine Cookies weg.
Für eine bessere oder sogar echte Lösung müssen Sie die Daten speichern, um einen gestarteten Prozess auf dem Server in einer Datenbank zu identifizieren. Da Flask datenbankunabhängig ist, habe ich kein Beispiel gefunden, da Sie in Ihrer Webanwendung einen völlig anderen Datenbankansatz verwenden können, als ich für das Beispiel gewählt hätte.
was ist das 'def (workit)'? und ist es innerhalb 'def downward()'? – ettanany
Ich habe bearbeitet. Jetzt sollte es klarer sein. Ja, es ist innerhalb von dowork(). Wie Sie sehen können, wird workit() zu einem Prozess. – Lucas
Es ist schwer, Ihrem Code zu folgen, da Ihr Einzug falsch ist, aber irgendwo in einem Funktionsaufruf '@ app.route ('/ stopwork', Methoden = ['POST'])'. Wenn diese Zeile zum ersten Mal ausgeführt wird, registriert sie den Endpunkt. Beim zweiten Mal versucht es den Endpunkt erneut zu registrieren und schlägt fehl. Sie sollten "stopwork" auf derselben Ebene wie doork definieren, so dass Sie den Endpunkt nur einmal registrieren. – dirn