/** * Read the python preamble off of stderr. It ends when the prompy '>>> ' is detected. * * @return the preamble read from stderr */ private String readPreamble(int timeoutMs) { String rv = null; StringBuilder sb = new StringBuilder(); long timeout = System.currentTimeMillis() + timeoutMs; try { char[] prompt = {'>', '>', '>', ' '}; int index = 0; while (true) { // sleep until there's input while (!stderr.ready()) { Thread.yield(); if (timeoutMs >= 0 && System.currentTimeMillis() >= timeout) error("Timeout (" + timeoutMs + " ms) reached while reading python preamble."); } int readInt = stderr.read(); if (readInt == -1) // end of stream error("End of output stream was reached while looking for python prompt."); char c = (char) readInt; sb.append(c); if (c == prompt[index]) { ++index; if (index == prompt.length) { // exit only if there are no more bytes to be read if (!stderr.ready()) break; else index = 0; } } else index = 0; } // trim off the prompt int len = sb.length(); sb.delete(len - prompt.length, len); // remove \n and \r if they're at the end of the string trimSuffix(sb, '\n'); trimSuffix(sb, '\r'); rv = sb.toString(); } catch (IOException e) { error("Error while reading python preamble.", e); } return rv; }
/** * Read stdout until the prompt '>>> ' is given on stderr * * @param quitOnStderr should we raise an exception if stderr output is detected other than the * prompt? * @return output the received stdout / stderr strings */ private String readUntilPrompt() { String rv = null; StringBuilder sbStdout = new StringBuilder(); StringBuilder sbStderr = new StringBuilder(); long timeout = System.currentTimeMillis() + timeoutMs; try { char[] prompt = {'>', '>', '>', ' '}; int index = 0; boolean done = false; while (!done) { // sleep until there's input while (!stdout.ready() && !stderr.ready()) { Thread.yield(); if (timeoutMs >= 0 && System.currentTimeMillis() >= timeout) { String out = ""; String err = ""; if (sbStdout.length() > 0) out = "\nStdout was: '" + sbStdout.toString() + "'"; if (sbStderr.length() > 0) err = "\nStderr was: '" + sbStderr.toString() + "'"; error("Timeout (" + timeoutMs + " ms) reached during python interaction." + out + err); } } // read stdout until blocked while (stdout.ready()) { int readInt = stdout.read(); if (readInt == -1) // end of stream error("End of output stream was reached while reading python response."); sbStdout.append((char) readInt); } // read stderr until blocked while (stderr.ready()) { int readInt = stderr.read(); if (readInt == -1) // end of stream error("End of output stream was reached while looking for python prompt."); char c = (char) readInt; sbStderr.append(c); if (c == prompt[index]) { ++index; if (index == prompt.length) { // exit only if there are no more bytes to be read if (!stderr.ready()) { done = true; break; } else index = 0; } } else index = 0; } } // read any remaining stdout characters sbStdout.append(readUntilBlocked(stdout)); // trim off the prompt sbStderr.delete(sbStderr.length() - prompt.length, sbStderr.length()); // trim off \n if it's at the end trimSuffix(sbStdout, '\n'); trimSuffix(sbStdout, '\r'); // if anything was printed to stderr, it's an error if (sbStderr.length() > 0) error( "Python produced output on stderr:\n'" + sbStderr.toString() + "'" + (sbStdout.length() > 0 ? "\n\nstdout was:\n" + sbStdout.toString() : "")); rv = sbStdout.toString(); } catch (IOException e) { error("Error while reading python output", e); } return rv; }