无需等待Python返回值就可以运行PHP代码

2024-09-18 15:22:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个PHP脚本,它使用

exec("C:/Python26/python C:/xampp/htdocs/timeout.py");

效果很好。但是Python代码在10分钟内返回一个值。我想在浏览器上显示echo "Time out";,不需要等待返回值。在

第一页.php

^{pr2}$

第二页.php

<?php

$start_time = time();
$timeVar=true;

while(true) {

    if ((time() - $start_time) < 300) {

        $read= exec("start C:/Python26/python C:/xampp/htdocs/test/timeout.py");
    }
    else
    {
        echo "Time out";
    }
}   
?>

超时.py

from multiprocessing 
import Process
import time 

def do_actions():    
    i = 0
    while True:
        i += 1
        # print(i)
        time.sleep(1) 

if __name__ == '__main__':
    # We create a Process
    action_process = Process(target=do_actions)

    # We start the process and we block for 5 seconds.
    action_process.start()
    action_process.join(timeout=600)

    # We terminate the process.
    action_process.terminate()
    print("Hey there! I timed out! You can do things after me!")

Tags: pytimetimeoutactionoutprocessdostart
1条回答
网友
1楼 · 发布于 2024-09-18 15:22:17

简介

你的代码和你用来做这件事的方法有很多问题。我将尽可能简单地回答这个问题,但请记住这不是一个容易的问题,它可能需要一些解释。在


代码的问题

首先,为什么现有的解决方案不起作用?我马上注意到的一些事情是:

  • 一个while(true)循环无限。由于您从未break离开它,因此此代码将永远无法完成执行。您可能打算使用$timeVar作为while循环的条件,并在代码中更改它,但从未这样做过。

  • 在每个循环中,如果时间不足300秒,则通过再次执行Python脚本,尝试再次读取它的输出。您在这里忘记了exec()是一个阻塞函数-这意味着在它完成之前不会执行任何操作-所以您只需等待脚本的整个执行-将其放入循环中并没有真正的改变。

当然,这些都是可以理解的错误。这是个难题。在


exec()函数

这个问题中的许多问题似乎归结为exec(),这个函数用于执行命令行语句,在执行任何其他代码之前等待语句完成。这是因为命令的实际工作方式-如果它们需要输出错误或输出,它们需要分别打印到stderr和{}。在PHP中,exec()充当stderr和{},因此命令需要能够在那里发送输出。这意味着PHP在命令完成之前不能继续前进。在

如果你用的是*nix系统,这会容易得多。但是,在Windows上,我们必须不再使用exec(),而是使用两个不同的函数:popen()和{}。在

首先,我们需要让命令在后台运行。这是一个非常简单的任务:在您的命令开始处,您已经编写了start,我们将改为编写start \b(在后台启动)。在

但是等等!如果命令总是在后台运行,我们如何获得结果?这就是重定向操作符>>的作用。它将shell函数的所有输出发送到一个文件中。因为我们使用了两个>字符,它将覆盖已经存在的任何文件。这将在以后变得重要。在

因此,在test目录(其中包含PHP和Python脚本)中创建一个文件夹,并将其命名为output。然后,我们将在PHP中为该文件生成一个名称,这样多个人就可以同时使用您的网站,而不必获得其他人的输出。我们可以使用time()函数来完成这项工作——它们不太可能在同一秒完成。现在您应该能够将输出发送到output目录中的一个文件,该文件将以当前的time()值命名。在

现在是最难的部分:执行它。popen()运行命令。它的第一个参数是命令,第二个参数是它的模式。它返回一个资源指针。您可以在下面链接的PHP手册上阅读这方面的内容。我们需要知道的是,在"r"模式下,如果出错,它也会返回一个资源(包含任何shell错误消息),因此它运行命令并始终返回一个需要关闭的指针。在

因此:

$filename = time().".txt";
pclose(popen("start \b C:/Python26/python C:/xampp/htdocs/test/timeout.py >> \"C:/xampp/htdocs/test/output/$filename\"", "r"));

应该在后台运行我们的命令。在

关于这个主题的进一步阅读:


整理第二页.php在

现在,我们在后台运行Python脚本。我们的PHP文件可以结束并向用户显示一个页面,Python仍然在服务器上运行。但是我们怎样才能得到输出呢?在

冷杉首先,我们需要记住文件名-将其存储在会话cookie中应该可以很好地工作。在最顶端第二页.php,我们需要添加代码session_start(),这样我们就可以使用会话cookie了。然后,我们将通过使用会话superglobal:$_SESSION["filename"] = $filename;设置文件名,将其存储在cookie中。在

我们需要做的另一件事是确保文件存在,这样我们可以稍后检查它是否为空(>>将用Python脚本的输出覆盖它,,但仅在脚本完成之后)。我们可以使用file_put_contents()创建文件。在

我们还需要包括一个JavaScript文件(我们还没有编写)。因此,这里是第二页.php

^{pr2}$

进一步阅读:

获取输出

现在,您需要编写一个新的PHP文件。把它叫做_输出.php。代码非常基本:

<?php
session_start(); //Allows us to use sessions

if (time()-$_SESSION["time"]>300) { //If the file was made more than 300 seconds (five minutes ago) we just echo timeout
    echo "Timeout";
}
else {
    echo file_get_contents("output/".$_SESSION["time"].".txt"); //Echo out the contents of the file. Pulls the filename out of our session cookie.
}
?>

希望这个文件是非常自解释的:它只是echo输出了输出文件的内容。在

现在,我们需要编写一个JavaScript文件。这将在用户计算机上运行,每五秒钟运行一次我们刚刚编写的PHP文件,这样我们就可以检查文件是否包含内容。它将把内容写到页面的正文。在

将此文件称为支票.js

function do_check() {
    var http = new XMLHttpRequest(); //Open a request to another page
    http.onreadystatechange = function() {
        if (http.readyState==4&&http.status==200) { //If we have loaded the page successfully
            document.body.innerHTML = http.responseText; //Set the body content to be the response text
        }
    }
    http.open("GET","get_output.php",true); //Request the file
    http.send(); //Send the request
}

setInterval("do_check()", 5000); //Call the function every five seconds.

进一步阅读:

结论

这应该是你所需要的。每五秒钟页面内容将被更改为文件的内容,您可以通过自己更改文件来进行检查-页面应更新以显示更改。在

相关问题 更多 >