def _redirect_output(self, statement):
"""Handles output redirection for >, >>, and |.
:param statement: ParsedString - subclass of str which also contains pyparsing ParseResults instance
"""
if statement.parsed.pipeTo:
self.kept_state = Statekeeper(self, ('stdout',))
# Create a pipe with read and write sides
read_fd, write_fd = os.pipe()
# Make sure that self.poutput() expects unicode strings in Python 3 and byte strings in Python 2
write_mode = 'w'
read_mode = 'r'
if six.PY2:
write_mode = 'wb'
read_mode = 'rb'
# Open each side of the pipe and set stdout accordingly
# noinspection PyTypeChecker
self.stdout = io.open(write_fd, write_mode)
# noinspection PyTypeChecker
subproc_stdin = io.open(read_fd, read_mode)
# We want Popen to raise an exception if it fails to open the process. Thus we don't set shell to True.
try:
self.pipe_proc = subprocess.Popen(shlex.split(statement.parsed.pipeTo), stdin=subproc_stdin)
except Exception as ex:
# Restore stdout to what it was and close the pipe
self.stdout.close()
subproc_stdin.close()
self.pipe_proc = None
self.kept_state.restore()
self.kept_state = None
# Re-raise the exception
raise ex
elif statement.parsed.output:
if (not statement.parsed.outputTo) and (not can_clip):
raise EnvironmentError('Cannot redirect to paste buffer; install ``xclip`` and re-run to enable')
self.kept_state = Statekeeper(self, ('stdout',))
self.kept_sys = Statekeeper(sys, ('stdout',))
if statement.parsed.outputTo:
mode = 'w'
if statement.parsed.output == 2 * self.redirector:
mode = 'a'
sys.stdout = self.stdout = open(os.path.expanduser(statement.parsed.outputTo), mode)
else:
sys.stdout = self.stdout = tempfile.TemporaryFile(mode="w+")
if statement.parsed.output == '>>':
self.poutput(get_paste_buffer())
评论列表
文章目录