简体   繁体   English

使用 request.post() 从 PHP controller 调用 python 脚本永远不会返回。 为什么?

[英]Calling python script with request.post() from PHP controller never returns. Why?

I am trying to execute a python script from a Laravel 8 app.我正在尝试从 Laravel 8 应用程序执行 python 脚本。 The python script uses the Laravel app's REST APIs so it has to authenticate. python 脚本使用 Laravel 应用程序的 REST API,因此它必须进行身份验证。

The python script runs great on it's own if its run at the command line (dev platform is Windows 10) but if run via shell_exec() or exec() or symfony/process() it takes down the Laravel app to the point where I need to restart the app on a different port or reboot with no errors in console, laravel log.如果 python 脚本在命令行运行(开发平台是 Windows 10),它自己运行得很好,但如果通过 shell_exec() 或 exec() 或 symfony/process() 运行,它会关闭 Laravel 应用程序到我需要在不同的端口上重新启动应用程序,或者在控制台 laravel 日志中没有错误的情况下重新启动。

If I take out the 'requests.post()' from the python script and replace it with print("Hello World") it works fine with the shell_exec()如果我从 python 脚本中取出 'requests.post()' 并将其替换为 print("Hello World") 它与 shell_exec() 一起工作正常

Question :Does anyone see what may be happening?问题:有人看到可能发生的事情吗? This seems like a permissions issue but I'm not sure.这似乎是一个权限问题,但我不确定。

Footnote : I tried Symfony but was getting an error that many others reported "failed to get random numbers to initialize Python runtime" This seems like a common problem on windows dev boxes.脚注:我尝试了 Symfony,但收到许多其他人报告的错误“无法获取随机数以初始化 Python 运行时”这似乎是 windows 开发箱上的常见问题。 Figured this problem out but the result is the same.想通了这个问题,但结果是一样的。 For anyone that sees this python initialization error in the future: On a windows build environment you need to add the environment variable SystemRoot as follows: $process = new Process([$python, $process_path, $argument1, $argument2], null, ['SystemRoot' => 'C:\WINDOWS']);对于以后看到此 python 初始化错误的任何人:在 windows 构建环境中,您需要添加环境变量 SystemRoot,如下所示: $process = new Process([$python, $process_path, $argument1, $argument2], null, ['SystemRoot' => 'C:\WINDOWS']);

Controller Controller

    public function startprocess(Request $request)
    {

        $python = "C:/Users/dev/AppData/Local/Programs/Python/Python38/python.exe";
        $process_path = "C:/Apache24/htdocs/project/resources/python/lambda/test.py";
        $complete_path = $python." ".$process_path;
        $output = [];
        $return_var = "";

//        exec($complete_path, $output, $return_var);
        $process = new Process([$python, $process_path], null, ['SystemRoot' => 'C:\WINDOWS']);
        $process->run();

        return view('admin.scheduledtasks_data', compact('output', 'return_var', 'complete_path'))->render();
    }

Python code Python 代码

import sys
import requests
from requests.exceptions import HTTPError
import re

url_login = 'http://127.0.0.1:8089/api/apilogin'

data = {
    'email': 'myemail@email.com',
    'password': 'password'}

returned_data = requests.post(url_login, data=data)  #<<THIS TAKES DOWN THE SERVER

Here is what the API resolves to这是 API 解决的问题

   public function APIlogin(Request $request)
    {

        $user = User::where('email', $request->email)->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            return response([
                'message' => ['Please submit a valid email address and password combination.']
            ], 404);
        }

        $token = $user->createToken('user-token')->plainTextToken;

        $response = [
            'user' => $user,
            'token' => $token
        ];

        return response($response, 201);
    }

Here is what a good request looks like from the command line这是从命令行发出的一个好的请求的样子

send: b'POST /api/apilogin HTTP/1.1 
Host: 127.0.0.1:8098 
User-Agent: python-requests/2.23.0 
Accept-Encoding: gzip, deflate 
Accept: */* 
Connection: keep-alive 
Content-Length: 48 
Content-Type: application/x-www-form-urlencoded'
send: b'email= (deleted) &password= (deleted)'
reply: 'HTTP/1.1 201 Created'
header: Host: 127.0.0.1:8098
header: Date: Fri, 13 Nov 2020 19:07:10 GMT
header: Connection: close
header: X-Powered-By: PHP/7.4.2
header: Cache-Control: no-cache, private
header: Date: Fri, 13 Nov 2020 19:07:10 GMT
header: Content-Type: application/json
header: X-RateLimit-Limit: 60
header: X-RateLimit-Remaining: 59

here is the response when I call it from laravel app using requests.post(url_login, data=data, timeout=3) with the 'timeout' added but the login never happens.这是当我使用 requests.post(url_login, data=data, timeout=3) 从 laravel 应用程序调用它并添加“超时”但登录从未发生时的响应。 Without the timeout the request never returns and server goes down没有超时,请求永远不会返回并且服务器停机

HTTP/1.1 200 OK
Host: 127.0.0.1:8102
Date: Fri, 13 Nov 2020 23:05:38 GMT
Connection: close
X-Powered-By: PHP/7.4.2
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, private
Date: Fri, 13 Nov 2020 23:05:38 GMT
Set-Cookie: XSRF-TOKEN= (deleted); 
    expires=Sat, 14-Nov-2020 01:05:38 GMT; 
    Max-Age=7200; 
    path=/
Set-Cookie: icollect_session=(deleted); 
    expires=Sat, 14-Nov-2020 01:05:38 GMT; 
    Max-Age=7200; 
    path=/; 
    httponly
<td>
<textarea class="form-control" id="FormControlTextarea" rows="10" cols="300">
send: b&#039;POST /api/apilogin HTTP/1.1\r\n
Host: 127.0.0.1:8102\r\n
User-Agent: python-requests/2.23.0\r\n
Accept-Encoding: gzip, deflate\r\n
Accept: */*\r\n
Connection: keep-alive\r\n
Content-Length: 48\r\n
Content-Type: application/x-www-form-urlencoded\r\n\r\n&#039;
send: b&#039;email=(deleted)&amp;password=(deleted);
</textarea>
</td>

update: The post never hits api.php so the problem must be something related to the python script not being able to post back to the app it was called from... but why?更新:帖子永远不会点击 api.php 所以问题一定与 python 脚本有关,无法回发到它被调用的应用程序......但为什么呢?

update: I am using JS ajax to call the PHP controller that spawns the python script.更新:我正在使用 JS ajax 调用生成 python 脚本的 PHP controller。 If I use the PHP symfony process() call in the controller to call the python script that contains the request.post() the ajax eventually errors out after 1 minute with a 500 error once Symfony throws a timing error and then the python script continues and works.如果我使用PHP symfony process()在controller中调用process()来拨打python脚本包含ajax的8827654043488脚本。和作品。 Now just to understand why and how to redesign this...现在只是为了了解为什么以及如何重新设计这个......

{message: "Maximum execution time of 60 seconds exceeded",…}
exception: "Symfony\Component\ErrorHandler\Error\FatalError"
file: "C:\Apache24\htdocs\laravel\vendor\symfony\process\Pipes\WindowsPipes.php"
line: 145
message: "Maximum execution time of 60 seconds exceeded"
trace: []

Got rid of Symfony process() and changed to this.摆脱了 Symfony process() 并更改为此。 What was happening is the laravel app was blocking the request.post from completing hence the lockup of the server...发生的事情是 laravel 应用程序阻止 request.post 完成,因此服务器锁定...

Found here --thank you @LucaM 在这里找到——谢谢@LucaM

function execInBackground($cmd) {
    if (substr(php_uname(), 0, 7) == "Windows"){
        pclose(popen("start /B ". $cmd, "r")); 
    }
    else {
        exec($cmd . " > /dev/null &");  
    }
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM