簡體   English   中英

創建執行python腳本的超鏈接(或按鈕),然后在腳本完成時重定向

[英]Create a hyperlink (or button) that executes a python script and then redirects when script completes

好吧,我設法讓它按我想要的方式工作(雖然有些/大多數人可能不同意這種方法)。 我按照下面的建議使用了Flask。 可能被視為“錯誤”的部分是404檢查循環。 這是不正確的設計,如果它持續太長時間,會導致某些瀏覽器出現“卡住腳本”錯誤。 但是,我想運行的腳本不會持續很長時間才能成為問題。

感謝您的幫助,如果您有任何其他建議,請與我們聯系。

燒瓶應用:

import threading
import subprocess
import os
import sys
from flask import Flask
from flask import render_template, abort
app = Flask(__name__)
app.debug = True

def run_script():
    theproc = subprocess.Popen([sys.executable, "run_me.py"])
    theproc.communicate()

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/generate')
def generate():
    threading.Thread(target=lambda: run_script()).start()
    return render_template('processing.html')

@app.route('/is_done')
def is_done():
    hfile = "templates\\itworked.html"
    if os.path.isfile(hfile):
        return render_template('itworked.html')
    else:
        abort(404)

if __name__ == "__main__":
    app.run()

processing.html:

<!DOCTYPE html>
<html>
<head>
    <script src="/static/jquery.min.js"></script>
</head>

<body>
<p>Processing...</p>
<script>
    setInterval(function()
    {
        var http = new XMLHttpRequest();
        http.open('HEAD', "is_done", false);
        http.send();
        if (http.status==200)
            window.location.replace("is_done");
    },2000);
</script>
</body>
</html>

原始問題:

我是初學者/中級Python程序員和初級Web開發人員所以請保持溫和。 我想要的:用戶點擊一個超鏈接,然后轉到一個中間網頁,上面寫着“正在處理......”。 在后台(在服務器上),此鏈接觸發一個python腳本,該腳本處理文件並創建新的網頁。 完成腳本后,用戶將被重定向到新創建的頁面。 我擁有:我有一個腳本來處理並吐出一個新的頁面。 我還沒想到的是如何觸發python腳本然后在腳本完成時觸發重定向。 我看過像django和cgi腳本這樣的web框架。 但我還沒有找到任何符合條件的東西。 我很可能會錯過一些完全明顯的東西,所以我真的很感激任何幫助。 謝謝。

解決這個問題的一個簡單方法是使用像Flask這樣的簡單Web框架來構建系統的Web部件。 在魔術鏈接的請求處理程序中,您需要生成腳本並跟蹤它。 查看腳本是否已完成並將其轉發給用戶的簡單方法是定期發送ajax請求以檢查完成情況。

例如,Flask網站可能如下所示:

import threading
import subprocess
import uuid
from flask import Flask
from flask import render_template, url_for, abort, jsonify, request
app = Flask(__name__)

background_scripts = {}

def run_script(id):
    subprocess.call(["/path/to/yourscript.py", "argument1", "argument2"])
    background_scripts[id] = True

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/generate')
def generate():
    id = str(uuid.uuid4())
    background_scripts[id] = False
    threading.Thread(target=lambda: run_script(id)).start()
    return render_template('processing.html', id=id)

@app.route('/is_done')
def is_done():
    id = request.args.get('id', None)
    if id not in background_scripts:
        abort(404)
    return jsonify(done=background_scripts[id])

index.html

<a href="{{ url_for('generate') }}">click me</a>

processing.html

<html>
<head>
<script src="/static/jquery.js"></script>
<script>
    function ajaxCallback(data) {
        if (data.done)
            window.location.replace("http://YOUR_GENERATED_PAGE_URL");
        else
            window.setTimeout(function() {
                $.getJSON('{{ url_for('is_done') }}', {id: {{ id }} }, ajaxCallback);
            }, 3000);
    }
    $(document).ready(function(){
        ajaxCallback({done=false});
    });
</script>
</head>
<body>
    Processing...
</body></html>

這是目前所有未經測試的代碼,但我希望您對如何解決此問題有所了解。 另請注意,這只有在您從一個進程提供頁面時才有效,因此如果您設置了Apache和mod_wsgi,請確保進程組中只有一個進程。

如果您需要更復雜的解決方案,您可能需要查看消息隊列等。

這對您來說可能是一個太重要的解決方案,但假設您無法取消“在服務器上創建文件”部分,這被認為是Web開發中的“最佳實踐”解決方案:

使用像Flask或Django這樣的Web框架來提供頁面。 當用戶請求通過請求啟動作業時(最好是POST請求,因為GET請求不應該導致嚴重的副作用),框架會向像Celery這樣的延遲任務系統發送消息。 然后向用戶顯示一個頁面,表明該作業已被提交。

此時,您可以使用ajax輪詢服務器並查看作業何時完成,但通常您不希望這是查看作業是否完成的唯一方法。 如果連接因任何原因而中斷,例如,如果用戶錯誤地關閉瀏覽器或選項卡(非常常見),則會浪費工作量並且用戶將不得不重新開始該過程。 如果可能的話,你應該有一種與用戶溝通的備份方式; 這可能是網站上其他地方出現的Flash消息,自動“完成工作”的電子郵件,主頁中顯示最近完成的作業的框,等等。這取決於用戶是否已登錄以及如何作業需要多長時間/是否除了創建文件之外還有副作用。

最后,您可以允許用戶通過該用戶的作業結果所特有的URL訪問該頁面。 請務必告知用戶該URL是否無限期無效,例如,如果該文件將在計時器上刪除。

兩種簡潔的方法:

1)使用ajax輪詢服務器。 每隔10秒或您認為合適的間隔檢查完成情況。 例如,當腳本正在處理時,它會寫入文件或數據庫,無論它指示完成百分比以及以某種方式識別進程(如果您有多個腳本同時運行,您將想知道哪個是鮑勃的,哪個是蘇茲的)。

2)禁用輸出緩沖並將輸出流式傳輸到客戶端。 這比第一個選項簡單。 基本上,運行腳本並在處理時,您可以輸出javascript代碼來說明,更新進度指示器。 您需要禁用輸出緩沖,或手動刷新緩沖區,否則您的客戶端可能不會立即收到輸出(指示器更新可能僅在客戶端達到100%時才可見)。 Google如何在您正在運行的任何設置(例如PHP,Django)上執行此操作。

你想要什么是可能的,但它確實是3個問題。

第一個問題是,如何從PHP創建新文件。 我真的不能回答這個問題。 您需要做什么,可能取決於您嘗試創建的文件類型和原因。

第二個問題是,如何讓用戶知道這種情況正在發生,第三個問題是如何重定向到新頁面。

就個人而言,我認為獲勝的最短路徑可能是讓您的客戶端javascript向服務器頁面或創建新內容的CGI模塊發出AJAX請求。

  1. 單擊按鈕,向生成新內容頁面的PHP頁面發出ajax請求。
  2. 出示你忙碌的指標。
  3. 讓請求的頁面返回新頁面的URL作為其內容。
  4. 當請求通過javascript完成重定向到返回的URL時。

作為Web開發的新手,最簡單的方法是查看jQuery及其AJAX功能。 那里的包裝使得上述操作非常容易。 當然,您也可以使用任何其他主要的JavaScript框架或直接的javascript。

以供參考:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM