Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用可读的非阻塞输出管道在linux上用python启动node.js子进程_Python_Node.js_Linux_Subprocess_Nonblocking - Fatal编程技术网

如何使用可读的非阻塞输出管道在linux上用python启动node.js子进程

如何使用可读的非阻塞输出管道在linux上用python启动node.js子进程,python,node.js,linux,subprocess,nonblocking,Python,Node.js,Linux,Subprocess,Nonblocking,我试图在python中创建node.js的子进程,以执行javascript代码并读取输出 这段代码在Windows10中运行,但在Ubuntu Linux上它给出了一个错误。当节点启动时,它会在stdout上给出一个提示,此代码尝试读取该提示,以验证节点已启动,并且管道可读,但在Linux上无法正常工作 import os import subprocess import time import re import json import logging logger = logging.g

我试图在python中创建node.js的子进程,以执行javascript代码并读取输出

这段代码在Windows10中运行,但在Ubuntu Linux上它给出了一个错误。当节点启动时,它会在stdout上给出一个提示
,此代码尝试读取该提示,以验证节点已启动,并且管道可读,但在Linux上无法正常工作

import os
import subprocess
import time
import re
import json
import logging

logger = logging.getLogger(__name__)

if "nt" == os.name:
    import msvcrt
    from ctypes import windll, byref, wintypes, GetLastError, WinError
    from ctypes.wintypes import HANDLE, DWORD, BOOL, LPDWORD
    PIPE_NOWAIT = wintypes.DWORD(0x00000001)
    ERROR_NO_DATA = 232
else:
    import fcntl

class NodeEngine:

    def __init__(self):
        self.stdout_fd = None
        self.p_stdout_fd = None
        self.stdout = None
        self.proc = None
        self.__init_pipes()

    def __init_pipes(self):
        self.stdout_fd, self.p_stdout_fd = os.pipe()
        self.pipe_no_wait(self.stdout_fd)
        self.stdout = os.fdopen(self.p_stdout_fd,"w")



    def pipe_no_wait(self, pipefd):

        if "nt" == os.name:
            SetNamedPipeHandleState = windll.kernel32.SetNamedPipeHandleState
            SetNamedPipeHandleState.argtypes = [HANDLE, LPDWORD, LPDWORD, LPDWORD]
            SetNamedPipeHandleState.restype = BOOL
            h = msvcrt.get_osfhandle(pipefd)
            res = windll.kernel32.SetNamedPipeHandleState(h, byref(PIPE_NOWAIT), None, None)
            if res == 0:
                print(WinError())
                return False
            return True
        else:
            fl = fcntl.fcntl(pipefd, fcntl.F_GETFL)
            fcntl.fcntl(pipefd, fcntl.F_SETFL, fl | os.O_NONBLOCK)

    def start(self):
        self.proc = subprocess.Popen(
            ["node","-i"],
            stdin=subprocess.PIPE,
            stdout=self.stdout,
            # stderr=subprocess.PIPE,
            shell=True
        )
        bytes_read = 0
        ret = ""
        timeout = time.time() + 10

        while 0 == bytes_read or 1024 == bytes_read:
            try:
                data = os.read(self.stdout_fd,1024)
                ret = ret + data.decode("utf-8")
                bytes_read = len(data)
            except Exception as e:
                if time.time() >= timeout:
                    raise e
                self.stdout.flush()
                bytes_read = 0



    def close(self):
        try:
            self.proc.stdin.close()
        except:
            pass

        self.proc.terminate()
        self.proc.wait(timeout=0.2)

if __name__ == '__main__':
    engine = NodeEngine()
    engine.start()

“刷新”命令似乎不起作用。有没有办法让它在Linux和Windows上正常工作?

我发现了这个bug,它非常微妙。当使用shell=True的Popen时,第一个参数不应该是列表

我变了

    self.proc = subprocess.Popen(
        ["node","-i"],
        stdin=subprocess.PIPE,
        stdout=self.stdout,
        # stderr=subprocess.PIPE,
        shell=True
    )

现在它可以在Linux和Windows上运行


注意:我将保留此问题,以便找到更好的解决方案

好的解决方案,拉尔夫!
    self.proc = subprocess.Popen(
        "node -i",
        stdin=subprocess.PIPE,
        stdout=self.stdout,
        # stderr=subprocess.PIPE,
        shell=True
    )