javascript Python脚本崩溃,但仅在从发布请求运行时崩溃

pftdvrlh  于 2023-01-19  发布在  Java
关注(0)|答案(1)|浏览(185)

我有一个post请求来生成一个子进程以运行discord_bot.py脚本并向其传递一个变量。
当我从终端运行脚本时,它运行得很好。但是,当我在我的NodeIdeJS应用程序中通过post路由运行它时,它总是在某个特定的点崩溃。
我已经张贴如下:
1.从我的server.js文件中发布路由代码。
1.来自我的discord_bot.py脚本的代码,**!!!!!!**在失败点。
1.我在控制台中遇到的错误。

从server.js发送路由

const mysql = require("mysql");
const discordbot = require("./config/discordbot.js");
const port = process.env.PORT || 3001;
const fs = require("fs-extra");
const router = express.Router();
const axios = require("axios");
const bodyParser = require("body-parser");
const cors = require("cors");

const app = express();
app.use(cors());
app.use(express.json());

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const spawner = require("child_process").spawn;
const promptCommand = "test output command";

app.post("/runPythonScript", (req, res) => {
    const pythonProcess = spawner("python", [
        path.join(__dirname, "public/py/discord_bot.py"),
        promptCommand,
    ]);
    console.log("Data sent to python script:", promptCommand);
    pythonProcess.stdout.on("data", (data) => {
        console.log("Data send back from python script:", data.toString());
        res.json({ message: "Python script is running" });
    });
    });

discord_bot.py中带有**!!!!!!**的代码位于故障点。

import sys
import os
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.relative_locator import locate_with
from dotenv import load_dotenv
load_dotenv()

# Initialize the browser instance
# path_to_chromedriver = 'C:/Users/mrthe/bootcamp/pydiscordbrowser/chromedriver.exe'
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
options = webdriver.ChromeOptions()
options.add_argument('--headless=False')

# Navigate to Discord
driver.get('https://discord.com/login')
time.sleep(2)

# Find the email and password fields and fill 'em in
time.sleep(2)
dlEMAIL = os.getenv('dlEMAIL')
dlPASSWORD = os.getenv('dlPASSWORD')

jxEMAIL = os.getenv('jxEMAIL')
jxPASSWORD = os.getenv('jxPASSWORD')

jxPyEMAIL = os.getenv('jxPyEMAIL')
jxPyPASSWORD = os.getenv('jxPyPASSWORD')

email_field = driver.find_element(By.NAME, 'email')
email_field.send_keys(jxPyEMAIL)
password_field = driver.find_element(By.NAME, 'password')
password_field.send_keys(jxPyPASSWORD)

# Find the login button on the login form and click it
time.sleep(1)
loginButton = driver.find_element(locate_with(By.TAG_NAME, "div").above({
    By.CLASS_NAME: "needAccount-MrvMN7"}).below({By.CLASS_NAME: "contents-3ca1mk"}))
loginButton.click()
print("##### Made it through login process")
sys.stdout.flush()

# Navigate to server and channel via URL
time.sleep(5)
driver.get("https://discord.com/channels/1063538236[REDACTED]/106353823690[REDACTED]")
print("##### Made it to the proper channel in the DL server")
sys.stdout.flush()

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

# Post in the channel
time.sleep(3)
# Get the active element
active_element = driver.execute_script("return document.activeElement")
print("##### got active element via script execution")
sys.stdout.flush()
time.sleep(3)
# Print the element to the console
print(active_element.get_attribute("outerHTML"))
print("#### printed active element to console")
sys.stdout.flush()
time.sleep(3)

# Send input to the active element

print("##### made it to first prompts variables blocks")
sys.stdout.flush()
text1 = "test output 1"
text2 = "test output 2"
text3 = "test output 3"

data_to_send_back = "Message from python script: Hello."
print("##### made it to commented out inputs/outputs")
sys.stdout.flush()
input = sys.argv\[1\]
output = data_to_send_back
print(output)

sys.stdout.flush()
print("##### made it to the send_keys list")
sys.stdout.flush()
active_element.send_keys(text1)
time.sleep(300/1000)
active_element.send_keys(Keys.SPACE)
time.sleep(300/1000)
active_element.send_keys(Keys.ENTER)

终端错误

[29220:31768:0118/170808.365:ERROR:cert_issuer_source_aia.cc(34)] Error parsing cert retrieved from AIA (as DER):
ERROR: Couldn't read tbsCertificate as SEQUENCE
ERROR: Failed parsing Certificate

Data send back from python script: ##### Made it to the proper channel in the DL server

node:_http_outgoing:644
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

∮我尝试过的事∮
我想我调用这个论证的方式可能有问题,所以为了测试,我完全删除了下面的代码块。

sys.stdout.flush()
input = sys.argv[1]
output = data_to_send_back
print(output)

这并没有改变行为。脚本仍然在完全相同的点崩溃(在上面的代码中用**!!!!!**标记)。
然而,如果我从终端而不是从post路径运行脚本,它运行得非常好。

2.

我实施了迈克尔M的建议,从他的评论和更新我的邮政路线代码如下。

app.post("/runPythonScript", async (req, res) => {
    const pythonProcess = spawner("python", [
        path.join(__dirname, "public/py/discord_bot.py"),
        promptCommand,
    ]);
    console.log("Data sent to python script:", promptCommand);

    let data = "";
    pythonProcess.stdout.on("data", (part) => (data += part));
    await new Promise((resolve) => pythonProcess.stdout.on("close", resolve));

    console.log("Data send back from python script:", data.toString());
    res.json({ message: "Python finished", data: data });
});

我们已经取得了进展,因为我现在在终端中得到了不同的错误,但脚本仍然在同一点崩溃。
这些是我现在收到的错误。

Error parsing cert retrieved from AIA (as DER):
ERROR: Couldn't read tbsCertificate as SEQUENCE
ERROR: Failed parsing Certificate

Data send back from python script: ##### Made it through login process
##### Made it to the proper channel in the DL server
##### got active element via script execution
mxg2im7a

mxg2im7a1#

问题出在您的服务器上。您的pythonProcess.stdout.on("data"处理程序可以多次运行,每次都使用新数据,但您只能调用res.json()一次,因为正如错误所述,它设置标头。请尝试使用promise和"close"事件:

app.post("/runPythonScript", async (req, res) => {
    const pythonProcess = spawner("python", [
        path.join(__dirname, "public/py/discord_bot.py"),
        promptCommand,
    ]);
    console.log("Data sent to python script:", promptCommand);

    let data = "";
    pythonProcess.stdout.on("data", part => data += part);
    await new Promise(resolve => pythonProcess.stdout.on("close", resolve));

    console.log("Data send back from python script:", data.toString());
    res.json({ message: "Python finished", data: data });
});

这将等待向变量添加任何新数据,然后等待进程结束。一旦进程结束,它将打印累积的数据并将其发送回客户端。

相关问题