Python 3.4.3 subprocess.Popen get output of command without piping?

前端 未结 4 1919
无人及你
无人及你 2021-02-06 05:32

I am trying to assign the output of a command to a variable without the command thinking that it is being piped. The reason for this is that the command in question gives unform

4条回答
  •  独厮守ぢ
    2021-02-06 05:45

    Yes, you can use the pty module.

    >>> import subprocess
    >>> p = subprocess.Popen(["ls", "--color=auto"], stdout=subprocess.PIPE)
    >>> p.communicate()[0]
    # Output does not appear in colour
    

    With pty:

    import subprocess
    import pty
    import os
    
    master, slave = pty.openpty()
    p = subprocess.Popen(["ls", "--color=auto"], stdout=slave)
    p.communicate()
    print(os.read(master, 100)) # Print 100 bytes
    # Prints with colour formatting info
    

    Note from the docs:

    Because pseudo-terminal handling is highly platform dependent, there is code to do it only for Linux. (The Linux code is supposed to work on other platforms, but hasn’t been tested yet.)

    A less than beautiful way of reading the whole output to the end in one go:

    def num_bytes_readable(fd):
        import array
        import fcntl
        import termios
        buf = array.array('i', [0])
        if fcntl.ioctl(fd, termios.FIONREAD, buf, 1) == -1:
            raise Exception("We really should have had data")
        return buf[0]
    
    print(os.read(master, num_bytes_readable(master)))
    

    Edit: nicer way of getting the content at once thanks to @Antti Haapala:

    os.close(slave)
    f = os.fdopen(master)
    print(f.read())
    

    Edit: people are right to point out that this will deadlock if the process generates a large output, so @Antti Haapala's answer is better.

提交回复
热议问题