Python 3.x 如何在事件处理程序中桥接用户与派生进程的通信
我的目标是在用户单击网页上的按钮后,使用另一个python脚本(需要一些shell交互才能输入身份验证代码)生成流程 register.py脚本有两种可能的shell结果,要么在用户未通过身份验证时要求输入身份验证代码,要么在结束时没有返回消息,表明用户已通过身份验证 到目前为止,我能够触发这个register.py文件,并通过socketio发出返回状态,如果脚本要求验证码或不要求,并将其显示给用户,但我不知道的是,我应该如何从网页上的用户输入中接受验证码,并在用户尚未验证的情况下再次将其加载到注册函数中 守则: Flask应用程序文件-代码是一个稍加调整的Flask SocketIO示例Python 3.x 如何在事件处理程序中桥接用户与派生进程的通信,python-3.x,flask,flask-socketio,Python 3.x,Flask,Flask Socketio,我的目标是在用户单击网页上的按钮后,使用另一个python脚本(需要一些shell交互才能输入身份验证代码)生成流程 register.py脚本有两种可能的shell结果,要么在用户未通过身份验证时要求输入身份验证代码,要么在结束时没有返回消息,表明用户已通过身份验证 到目前为止,我能够触发这个register.py文件,并通过socketio发出返回状态,如果脚本要求验证码或不要求,并将其显示给用户,但我不知道的是,我应该如何从网页上的用户输入中接受验证码,并在用户尚未验证的情况下再次将其加载
from threading import Lock
from flask import Flask, render_template, session, request
from flask_socketio import SocketIO, emit, disconnect
import pexpect
async_mode = None
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode=async_mode)
thread = None
thread_lock = Lock()
def register(username, phone):
child = pexpect.spawn('python3 register.py -u ' + username + ' -p ' + phone )
i = child.expect(['Please enter the code .*', pexpect.EOF])
socketio.emit('my_response', {'data': 'pexpect result ' + str(i) + ' ' + child.after.decode(), 'count': 55555}, namespace='/test')
@app.route('/')
def index():
return render_template('index.html')
@socketio.on("authenticate", namespace="/test")
def authenticate(message):
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(target=lambda: register("radicz", "+999999000999"))
if __name__ == '__main__':
socketio.run(app, debug=True)
HTML文件
<!DOCTYPE HTML>
<html>
<head>
<title>Flask-SocketIO Test</title>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
// Use a "/test" namespace.
// An application can open a connection on multiple namespaces, and
// Socket.IO will multiplex all those connections on a single
// physical channel. If you don't care about multiple channels, you
// can set the namespace to an empty string.
namespace = '/test';
// Connect to the Socket.IO server.
// The connection URL has the following format:
// http[s]://<domain>:<port>[/<namespace>]
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
// Event handler for new connections.
// The callback function is invoked when a connection with the
// server is established.
socket.on('connect', function() {
socket.emit('my_event', {data: 'I\'m connected!'});
});
$("#register").on("click", function(){
socket.emit("authenticate", {data: "cislo + jmeno"})
console.log("register fired!");
});
// Event handler for server sent data.
// The callback function is invoked whenever the server emits data
// to the client. The data is then displayed in the "Received"
// section of the page.
socket.on('my_response', function(msg) {
$('#log').append('<br>' + $('<div/>').text('Received #' + msg.count + ': ' + msg.data).html());
});
// Handlers for the different forms in the page.
// These accept data from the user and send it to the server in a
// variety of ways
$('form#emit').submit(function(event) {
socket.emit('my_event', {data: $('#emit_data').val()});
return false;
});
$('form#disconnect').submit(function(event) {
socket.emit('disconnect_request');
return false;
});
});
</script>
</head>
<body>
<h1>Flask-SocketIO Test</h1>
<button id="register">register</button>
<h2>Send:</h2>
<form id="emit" method="POST" action='#'>
<input type="text" name="emit_data" id="emit_data" placeholder="Message">
<input type="submit" value="Echo">
</form>
<form id="disconnect" method="POST" action="#">
<input type="submit" value="Disconnect">
</form>
<h2>Receive:</h2>
<div id="log"></div>
</body>
</html>
烧瓶冲击试验
$(文档).ready(函数(){
//使用“/test”命名空间。
//应用程序可以在多个名称空间上打开连接,并且
//Socket.IO将在单个端口上多路传输所有这些连接
//物理通道。如果你不关心多个通道,你
//可以将命名空间设置为空字符串。
名称空间='/test';
//连接到Socket.IO服务器。
//连接URL具有以下格式:
//http[s]:/:[/]
var socket=io.connect(location.protocol+'/'+document.domain+':'+location.port+名称空间);
//新连接的事件处理程序。
//当与
//服务器已建立。
socket.on('connect',function(){
emit('my_event',{data:'I'm connected!'});
});
$(“#注册”)。在(“单击”,函数(){
emit(“authenticate”{data:“cislo+jmeno”})
log(“register fired!”);
});
//服务器发送数据的事件处理程序。
//只要服务器发出数据,就会调用回调函数
//发送到客户端。然后,数据显示在“已接收”中
//本页的第节。
socket.on('my_response',函数(msg){
$('#log').append('
'+$('').text('Received#'+msg.count+':'+msg.data.html());
});
//页面中不同窗体的处理程序。
//它们接受来自用户的数据,并以一种特定的方式将其发送到服务器
//多种方式
$('form#emit').submit(函数(事件){
emit('my_event',{data:$('#emit_data').val()});
返回false;
});
$('form#disconnect').submit(函数(事件){
发出('disconnect_request');
返回false;
});
});
烧瓶冲击试验
登记
发送:
收到:
所以问题是,如何获得用户提供的身份验证代码并将其加载到注册函数中?我想我可以使用一些让步技巧,比如如果需要从服务器端进行身份验证,则发出,然后从客户端发出事件,再次触发后端的注册函数,但该函数将从上次让步时开始继续,但我不确定如何正确执行,或者它的可行方法,或者我完全走神了,还有其他一些技术可以更轻松地完成这项任务
编辑:或者可能是正确的方法?我没有很好地测试它,但似乎在寄存器函数中添加另一个socketio事件处理程序有助于我达到目的
def register(username, phone):
child = pexpect.spawn('python3 register.py -u ' + username + ' -p ' + phone )
i = child.expect(['Please enter the code .*', pexpect.EOF])
socketio.emit('my_response', {'data': 'pexpect result ' + str(i) + ' ' + child.after.decode(), 'count': 55555}, namespace='/test')
@socketio.on("another_event", namespace="/test")
def another_callback(message):
# actual code that I wanted to run
(请在单独的问题帖中提出附加问题,谢谢。)