Pass integer input argument for Popen.communicate()

前端 未结 3 451
走了就别回头了
走了就别回头了 2021-01-26 11:04

I am pretty new to python and I am stuck with something now. I am using python 2.7. I am trying to automate a command in shell for which I wrote a python script. I have to input

相关标签:
3条回答
  • 2021-01-26 11:22

    Pipes are byte streams in Unix. There is no numeric input -- there is only "string" input (there are no numbers or anything else -- there are only bytes).

    If your child java process expects a number as its ascii representation then .communicate(input='2') is correct already if the subprocess reads from stdin (System.in). If the java process reads from the console directly (System.console().readLine()) then stdin=PIPE won't work (you might need to provide a pty in this case e.g., using pexpect).

    For example, to read an integer from stdin and print it back in Java:

    import java.util.Scanner;
    
    public class ReadInteger
    {
      public static void main(String args[])
      {
        Scanner in = new Scanner(System.in);
        int i = in.nextInt();
        System.out.println("got " + i);
      }
    }
    

    To pass an integer from Python process to the Java process via a pipe:

    #!/usr/bin/env python2
    from subprocess import Popen, PIPE
    
    p = Popen(['java', '-ea', 'ReadInteger'], stdin=PIPE, stdout=PIPE)
    output = p.communicate(input='2')[0]
    print 'from java {' + output.strip() + '}'
    

    It works (the output is from java {got 2}).

    It stops working if the child process reads from the console instead:

    public class ReadIntegerConsole
    {
      public static void main(String args[])
      {
        int i = Integer.parseInt(System.console().readLine());
        System.out.println("got " + i);
      }
    }
    

    The same python script leads to NullPointerException (and the output is from java {}) because System.console() is null here (stdin is redirected). It works if we provide a pseudo-tty:

    #!/usr/bin/env python2
    import pexpect # $ pip install pexpect
    
    child = pexpect.spawn('java -ea ReadIntegerConsole')
    child.setecho(False)
    child.sendline('2')
    child.expect(pexpect.EOF)
    child.close()
    print "from java {" + child.before.strip() + "}"
    

    It works (the output is from java {got 2}).

    0 讨论(0)
  • 2021-01-26 11:27

    Finally I found the solution for this. Well the solution to this was pretty simple


    when I changed

    string = proc.communicate(input='2')

    to

    string = proc.communicate(input='2\n')

    it worked fine.

    0 讨论(0)
  • 2021-01-26 11:32

    The ./sbt process you are calling needs to be able to read a string and convert it into a integer. It is not possible to send native Python types to a child process with only Popen.

    Another potential solution would be to serialize the data into JSON, YAML, XML, python pickle format, etc - choose your standard. However as you are passing a single integer this would seem very much overkill.

    0 讨论(0)
提交回复
热议问题