def _read_commands(self): "works in separate thread" while True: line = sys.stdin.readline() if line == "": logger.info("Read stdin EOF") sys.exit() cmd = parse_message(line) self._command_queue.put(cmd)
def publish_as_msg(data): msg = parse_message(data) if "cwd" in msg: self.cwd = msg["cwd"] message_queue.append(msg) while len(message_queue) > 100: # Probably backend runs an infinite/long print loop. # Throttle message thougput in order to keep GUI thread responsive. sleep(0.1)
def _read_one_incoming_message(self): line = self._read_incoming_msg_line() if line == "": return False msg = parse_message(line) if isinstance(msg, ImmediateCommand): # This will be handled right away self._handle_immediate_command(msg) else: self._incoming_message_queue.put(msg) return True
def _read_incoming_messages(self): # works in a separate thread while self._should_keep_going(): line = self._read_incoming_msg_line() if line == "": break msg = parse_message(line) if isinstance(msg, ImmediateCommand): # This will be handled right away self._handle_immediate_command(msg) else: self._incoming_message_queue.put(msg)
def _read_commands(self): "works in separate thread" while True: line = sys.stdin.readline() if line == "": logger.info("Read stdin EOF") sys.exit() cmd = parse_message(line) if isinstance(cmd, InterruptCommand): # This is a priority command and will be handled right away self._interrupt_in_command_reading_thread() else: self._command_queue.put(cmd)
def _listen_stdout(self): #debug("... started listening to stdout") # will be called from separate thread while True: data = self._proc.stdout.readline() #debug("... read some stdout data", repr(data)) if data == '': break else: msg = parse_message(data) if "cwd" in msg: self.cwd = msg["cwd"] with self._state_lock: self._message_queue.append(msg)
def _listen_stdout(self): #debug("... started listening to stdout") # will be called from separate thread while True: data = self._proc.stdout.readline().decode(COMMUNICATION_ENCODING) #debug("... read some stdout data", repr(data)) if data == '': break else: #print("MSG", data) msg = parse_message(data) if hasattr(msg, "cwd"): self.cwd = msg.cwd with self._state_lock: self._message_queue.append(msg) if isinstance(msg, PauseMessage): self._current_pause_msg = msg
def _listen_stdout(self): #debug("... started listening to stdout") # will be called from separate thread while True: data = self._proc.stdout.readline() #debug("... read some stdout data", repr(data)) if data == '': break else: msg = parse_message(data) if "cwd" in msg: self.cwd = msg["cwd"] # TODO: it was "with self._state_lock:". Is it necessary? self._message_queue.append(msg) if len(self._message_queue) > 100: # Probably backend runs an infinite/long print loop. # Throttle message thougput in order to keep GUI thread responsive. sleep(0.1)
def _start_new_process(self, cmd=None): # deque, because in one occasion I need to put messages back self._message_queue = collections.deque() # prepare environment my_env = get_environment_for_python_subprocess(self._executable) # variables controlling communication with the back-end process my_env["PYTHONIOENCODING"] = "utf-8" # Let back-end know about plug-ins my_env["THONNY_USER_DIR"] = THONNY_USER_DIR if get_workbench().in_debug_mode(): my_env["THONNY_DEBUG"] = "1" elif "THONNY_DEBUG" in my_env: del my_env["THONNY_DEBUG"] if not os.path.exists(self._executable): raise UserError( "Interpreter (%s) not found. Please recheck corresponding option!" % self._executable) import thonny.backend_launcher cmd_line = [ self._executable, "-u", # unbuffered IO "-B", # don't write pyo/pyc files # (to avoid problems when using different Python versions without write permissions) thonny.backend_launcher.__file__, ] if hasattr(cmd, "filename"): cmd_line.append(cmd.filename) if hasattr(cmd, "args"): cmd_line.extend(cmd.args) if hasattr(cmd, "environment"): my_env.update(cmd.environment) creationflags = 0 if running_on_windows(): creationflags = subprocess.CREATE_NEW_PROCESS_GROUP debug("Starting the backend: %s %s", cmd_line, get_workbench().get_local_cwd()) self._proc = subprocess.Popen( cmd_line, # bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=get_workbench().get_local_cwd(), env=my_env, universal_newlines=True, creationflags=creationflags, ) # send init message self._send_msg({"frontend_sys_path": sys.path}) if cmd: # Consume the ready message, cmd will get its own result message ready_line = self._proc.stdout.readline() if ready_line == "": # There was some problem error_msg = self._proc.stderr.read() raise Exception("Error starting backend process: " + error_msg) self._store_state_info(parse_message(ready_line)) # setup asynchronous output listeners Thread(target=self._listen_stdout, daemon=True).start() Thread(target=self._listen_stderr, daemon=True).start()
def _fetch_command(self): line = self._original_stdin.readline() if line == "": sys.exit() cmd = parse_message(line) return cmd
def _start_new_process(self, cmd): self._message_queue = collections.deque() # create new backend process my_env = {} for name in os.environ: if ("python" not in name.lower() # skip python vars, because we may use different Python version and name not in ["TK_LIBRARY", "TCL_LIBRARY"]): # They tend to point to frontend Python installation my_env[name] = os.environ[name] # TODO: take care of SSL_CERT_FILE # Unset when we're in builtin python and target python is external my_env["PYTHONIOENCODING"] = "ASCII" my_env["PYTHONUNBUFFERED"] = "1" if not os.path.exists(self._executable): raise UserError("Interpreter (%s) not found. Please recheck corresponding option!" % self._executable) if is_private_interpreter(self._executable): # in gui environment make "pip install" # use a folder outside thonny installation # in order to keep packages after reinstalling Thonny my_env["PIP_USER"] = "******" my_env["PYTHONUSERBASE"] = THONNY_USER_DIR backend_launcher = os.path.join(get_workbench().get_package_dir(), "backend_private", "thonny_backend.py") if not os.path.exists(backend_launcher): # in dev machine use the main source backend_launcher = os.path.realpath( os.path.join(get_workbench().get_package_dir(), "..", "thonny_backend.py") ) cmd_line = [ self._executable, '-u', # unbuffered IO (neccessary in Python 3.1) '-B', # don't write pyo/pyc files # (to avoid problems when using different Python versions without write permissions) backend_launcher ] if hasattr(cmd, "filename"): cmd_line.append(cmd.filename) if hasattr(cmd, "args"): cmd_line.extend(cmd.args) if hasattr(cmd, "environment"): my_env.update(cmd.environment) debug("Starting the backend: %s %s", cmd_line, self.cwd) self._proc = subprocess.Popen ( cmd_line, #bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.cwd, env=my_env, universal_newlines=True ) ready_line = self._proc.stdout.readline() if ready_line == "": # There was some problem error_msg = self._proc.stderr.read() raise Exception("Error starting backend process: " + error_msg) ready_msg = parse_message(ready_line) debug("Backend ready: %s", ready_msg) get_workbench().event_generate("BackendReady", **ready_msg) # setup asynchronous output listeners start_new_thread(self._listen_stdout, ()) start_new_thread(self._listen_stderr, ())