stderr of the child processes should be printed in debug output

This fixes #1169. It might have a bit of a different intention, but at least it's now possible to see output of the subprocess and it's not just a black hole.
This commit is contained in:
Dave Halter
2018-08-03 13:35:21 +02:00
parent ccb460b433
commit 1c76359291
2 changed files with 33 additions and 5 deletions

View File

@@ -369,6 +369,7 @@ def print_to_stderr(*args):
eval("print(*args, file=sys.stderr)")
else:
print >> sys.stderr, args
sys.stderr.flush()
def utf8_repr(func):

View File

@@ -15,9 +15,15 @@ import errno
import weakref
import traceback
from functools import partial
from threading import Thread
try:
from Queue import Queue, Empty
except ImportError:
from queue import Queue, Empty # python 3.x
from jedi._compatibility import queue, is_py3, force_unicode, \
pickle_dump, pickle_load, GeneralizedPopen
from jedi import debug
from jedi.cache import memoize_method
from jedi.evaluate.compiled.subprocess import functions
from jedi.evaluate.compiled.access import DirectObjectAccess, AccessPath, \
@@ -28,6 +34,12 @@ from jedi.api.exceptions import InternalError
_MAIN_PATH = os.path.join(os.path.dirname(__file__), '__main__.py')
def _enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
def _get_function(name):
return getattr(functions, name)
@@ -142,7 +154,7 @@ class CompiledSubprocess(object):
os.path.dirname(os.path.dirname(parso_path)),
'.'.join(str(x) for x in sys.version_info[:3]),
)
return GeneralizedPopen(
process = GeneralizedPopen(
args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
@@ -151,6 +163,14 @@ class CompiledSubprocess(object):
# (this is already the case on Python 3).
bufsize=-1
)
self._stderr_queue = Queue()
self._stderr_thread = t = Thread(
target=_enqueue_output,
args=(process.stderr, self._stderr_queue)
)
t.daemon = True
t.start()
return process
def run(self, evaluator, function, args=(), kwargs={}):
# Delete old evaluators.
@@ -219,6 +239,15 @@ class CompiledSubprocess(object):
stderr,
))
while True:
# Try to do some error reporting from the subprocess and print its
# stderr contents.
try:
line = self._stderr_queue.get_nowait()
debug.warning('stderr output: %s' % line.rstrip('\n'))
except Empty:
break
if is_exception:
# Replace the attribute error message with a the traceback. It's
# way more informative.
@@ -282,11 +311,9 @@ class Listener(object):
def listen(self):
stdout = sys.stdout
# Mute stdout/stderr. Nobody should actually be able to write to those,
# because stdout is used for IPC and stderr will just be annoying if it
# leaks (on module imports).
# Mute stdout. Nobody should actually be able to write to it,
# because stdout is used for IPC.
sys.stdout = open(os.devnull, 'w')
sys.stderr = open(os.devnull, 'w')
stdin = sys.stdin
if sys.version_info[0] > 2:
stdout = stdout.buffer