Python3 how to pass binary data to stdin when using subprocess.run()?

Viewed 2099

So how do I pass binary data using stdin to a executable command that I want to run using subprocess.run()?

The documentation is pretty vague about using the stdin for passing the data to external executable. I'm working on linux machine using python3 and I want to invoke dd of=/somefile.data bs=32 (which takes the input from stdin if I understand the man page correctly) and I have the binary data in bytearray that I want to pass to the command through stdin so that I do not have to write it to a temporary file and invoke the dd using that file as a input.

My requirement is simply to pass data that I have in bytearray to the dd command to be written to disk. What is the correct way to achieve this using the subprocess.run() and stdin?

Edit: I meant something like the following:

ba = bytearray(b"some bytes here")
#Run the dd command and pass the data from ba variable to its stdin
2 Answers

You can pass the output of one command to another by calling Popen directly.

file_cmd1 = <your dd command>
file_cmd2 = <command you want to pass dd output to>

proc1 = Popen(sh_split(file_cmd1), stdout=subprocess.PIPE)
proc2 = Popen(file_cmd2, [shell=True], stdin=proc1.stdout, stdout=subprocess.PIPE)
proc1.stdout.close()

This, as far as I know, will work just fine on a byte output from command 1.

In your case what you most like want to do is the following when you just want to pass data to the stdin of the process:

out = bytearray(b"Some data here")
p = subprocess.Popen(sh_split("dd of=/../../somefile.data bs=32"), stdin=subprocess.PIPE)
out = p.communicate(input=b''.join(out))[0]
print(out.decode())#Prints the output from the dd

Specifically for stdin to subprocess.run() as asked by the OP, use input as follows:

#!/usr/bin/python3
import subprocess

data = bytes("Hello, world!", "ascii")

p = subprocess.run(
    "cat -", # The - means 'cat from stdin'
    input=data,
    # stdin=... <-- don't use this
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
)

print(p.stdout.decode("ascii"))
print(p.returncode)

# Hello, world!
# 0
Related