创建一个执行python脚本的超链接(或按钮),然后在脚本完成时重定向 [英] Create a hyperlink (or button) that executes a python script and then redirects when script completes

查看:280
本文介绍了创建一个执行python脚本的超链接(或按钮),然后在脚本完成时重定向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我设法让它工作得如何(尽管有些/大多数人可能会不同意这种方法)。我按照下面的建议使用了Flask。可能被认为是错误的部分是404检查循环。这是不适当的设计,并导致一些浏览器的卡住脚本错误,如果它继续太久。然而,我想运行的脚本持续时间不够长,以至于无法解决问题。



感谢您的帮助,请让我知道您是否有其他人建议。



Flask应用程序:

 导入线程
导入子进程
导入os
导入sys $ b $ from烧瓶导入烧瓶
从烧瓶导入render_template,中止
app =烧瓶(__ name__)
app.debug = True
$ b $ 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
如果os.path.isfile(hfile) :
re打开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>正在处理...< / 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框架。但我还没有发现任何我觉得符合法案的东西。我很可能错过了一些完全明显的东西,所以我非常感谢任何帮助。
Thanks。

解决方案

解决此问题的一个简单方法是使用简单的Web框架像Flask在你的系统上构建Web部件。在魔术链接的请求处理程序中,您需要生成脚本并跟踪它。查看脚本是否完成并将其转发给用户的一个简单方法是定期发送ajax请求来检查完成。



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

 导入线程
导入子流程
从烧瓶导入导入uuid
烧瓶
from flask import render_template,url_for,abort,jsonify,request
app = Flask(__ name__)

background_scripts = {}
$ b $ 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)
如果id不在background_scripts中:
abort(404)
return jsonify(done = background_scripts [id])

index.html :

 < a href ={{url_for('generate')}}>点击我< / a> 

processing.html

 < html> 
< head>
< script src =/ static / jquery.js>< / script>
< script>
函数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>
处理中...
< / body>< / html>

这是目前所有未经测试的代码,但我希望您对如何解决此问题有所了解问题。另外请记住,只有当您从一个进程提供页面时才能使用,所以如果您设置了Apache和mod_wsgi,请确保进程组中只有一个进程。



如果您需要更复杂的解决方案,您可能需要查看消息队列等。


Alright, I managed to get it working how I want (although some/most might disagree with the method). I used Flask as recommended below. The part that might be considered "wrong" is the 404 check loop. It isn't proper design and results in a "stuck script" error in some browsers if it goes on for too long. However, the script I want to run doesn't last long enough for that to be a problem.

Thanks for the help and please let me know if you have any other suggestions.

Flask App:

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>

Original question:

I am a beginner/intermediate Python programmer and a beginning web developer so please be gentle. What I want: A user clicks a hyperlink and is taken to an intermediate web page that says something like "Processing...". In the background (on the server) this link triggers a python script that processes a file and creates a new web page. On completion of the script, the user is redirected to the newly created page. What I have: I have a script that does the processing and spits out a new page. What I haven't figured out is how to trigger the python script and then trigger the redirect on script completion. I've looked at web frameworks like django, and cgi scripting. But I haven't found anything I feel fits the bill. It's very possible I'm just missing something completely obvious so I'd really appreciate any help. Thanks.

解决方案

A simple way to tackle this problem would be to use a simple web framework like Flask to build the web part uf your system. In the request handler for your magic link, you would need to spawn your script and keep track of it. A simple way to see if your script is done and relay that to your user is to periodically send off an ajax request to check for completion.

So for example the Flask website could look like:

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])

And the index.html:

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

And 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>

This is all untested code at the moment, but I hope you get some idea on how to approach this problem. Also keep in mind that this will only work if you serve the page from one process, so if you set up Apache and mod_wsgi, make sure there is only one process in the process group.

If you need a more complex solution, you might want to look at message queues and the like.

这篇关于创建一个执行python脚本的超链接(或按钮),然后在脚本完成时重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆