How can I start a node.js subprocess in python on linux with a readable non-blocking output pipe

Multi tool use
up vote
2
down vote
favorite
I am trying to create a subprocess of node.js in python to execute javascript code and read the output.
This code works in Windows 10 but on Ubuntu Linux it gives an error. When node starts it gives a prompt of >
on stdout and this code attempts to read that prompt to verify that node has started and that the pipe is readable but it doesn't work correctly on 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()
It seems the flush command isn't working. Is there a way to get this to work properly on Linux and Windows?
python node.js linux subprocess nonblocking
add a comment |
up vote
2
down vote
favorite
I am trying to create a subprocess of node.js in python to execute javascript code and read the output.
This code works in Windows 10 but on Ubuntu Linux it gives an error. When node starts it gives a prompt of >
on stdout and this code attempts to read that prompt to verify that node has started and that the pipe is readable but it doesn't work correctly on 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()
It seems the flush command isn't working. Is there a way to get this to work properly on Linux and Windows?
python node.js linux subprocess nonblocking
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I am trying to create a subprocess of node.js in python to execute javascript code and read the output.
This code works in Windows 10 but on Ubuntu Linux it gives an error. When node starts it gives a prompt of >
on stdout and this code attempts to read that prompt to verify that node has started and that the pipe is readable but it doesn't work correctly on 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()
It seems the flush command isn't working. Is there a way to get this to work properly on Linux and Windows?
python node.js linux subprocess nonblocking
I am trying to create a subprocess of node.js in python to execute javascript code and read the output.
This code works in Windows 10 but on Ubuntu Linux it gives an error. When node starts it gives a prompt of >
on stdout and this code attempts to read that prompt to verify that node has started and that the pipe is readable but it doesn't work correctly on 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()
It seems the flush command isn't working. Is there a way to get this to work properly on Linux and Windows?
python node.js linux subprocess nonblocking
python node.js linux subprocess nonblocking
asked Nov 10 at 15:43
Ralph Ritoch
1,8841527
1,8841527
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
I found the bug and it was very subtle. When using Popen with shell=True the first argument shouldn't be a list.
I changed
self.proc = subprocess.Popen(
["node","-i"],
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
to
self.proc = subprocess.Popen(
"node -i",
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
and now it works on both Linux and Windows.
Note: I'll leave this question open for better solutions
Good catch Ralph!
– pygo
Nov 10 at 17:53
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
I found the bug and it was very subtle. When using Popen with shell=True the first argument shouldn't be a list.
I changed
self.proc = subprocess.Popen(
["node","-i"],
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
to
self.proc = subprocess.Popen(
"node -i",
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
and now it works on both Linux and Windows.
Note: I'll leave this question open for better solutions
Good catch Ralph!
– pygo
Nov 10 at 17:53
add a comment |
up vote
0
down vote
I found the bug and it was very subtle. When using Popen with shell=True the first argument shouldn't be a list.
I changed
self.proc = subprocess.Popen(
["node","-i"],
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
to
self.proc = subprocess.Popen(
"node -i",
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
and now it works on both Linux and Windows.
Note: I'll leave this question open for better solutions
Good catch Ralph!
– pygo
Nov 10 at 17:53
add a comment |
up vote
0
down vote
up vote
0
down vote
I found the bug and it was very subtle. When using Popen with shell=True the first argument shouldn't be a list.
I changed
self.proc = subprocess.Popen(
["node","-i"],
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
to
self.proc = subprocess.Popen(
"node -i",
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
and now it works on both Linux and Windows.
Note: I'll leave this question open for better solutions
I found the bug and it was very subtle. When using Popen with shell=True the first argument shouldn't be a list.
I changed
self.proc = subprocess.Popen(
["node","-i"],
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
to
self.proc = subprocess.Popen(
"node -i",
stdin=subprocess.PIPE,
stdout=self.stdout,
# stderr=subprocess.PIPE,
shell=True
)
and now it works on both Linux and Windows.
Note: I'll leave this question open for better solutions
answered Nov 10 at 17:44
Ralph Ritoch
1,8841527
1,8841527
Good catch Ralph!
– pygo
Nov 10 at 17:53
add a comment |
Good catch Ralph!
– pygo
Nov 10 at 17:53
Good catch Ralph!
– pygo
Nov 10 at 17:53
Good catch Ralph!
– pygo
Nov 10 at 17:53
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53240567%2fhow-can-i-start-a-node-js-subprocess-in-python-on-linux-with-a-readable-non-bloc%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
q2 K3 zQh 0,EpOGRcjX9YxarxFdBvUxPgz f6hz2op4Ni95 rtiDd3PS3