9

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
  • You can set stdin=<something> when using Popen, but not sure you can set it to be just stdin, you need to gather your input first, then pass it to the subprocess. If you have another process generating output that you want to use as stdin here you can certainly do that though - i.e. stdin for proc2 is output from proc1. SO proc1 would be your dd command, and proc2 would be whatever process you want to pass the output to. Not sure if this helps - I'm a little unclear as to the exact requirement here. Commented Jul 21, 2020 at 10:39
  • @urbanespaceman My requirement is simply to pass data that I have in bytearray to the dd command to be written to disk. Editing the question. Commented Jul 21, 2020 at 10:42

2 Answers 2

4

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
Sign up to request clarification or add additional context in comments.

1 Comment

simplification for 3.7+: use the argument capture_output=True instead of stdout=PIPE,stderr=PIPE
2

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

4 Comments

Umm I do not run a command from where to get the stdout to pass to the second Popen. Can I just pass the bytearray type variable where I have the data in the place of proc1.stdout instead? The data itself is formed in the python program and is stored in a bytearray type variable.
Sorry, I think I misunderstood. stdin requires a byte sequence, so I guess this should work if you pass bytearray directly to that ... if it doesn't then just send the straight byte sequence without turning it into a bytearray.
How should I input the byte sequence? Tried the following: proc = subprocess.Popen(shsplit("dd of=/home/xyz/test.txt bs=1 seek=0"), stdin=b'Hello World', stdout=subprocess.PIPE) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.8/subprocess.py", line 804, in __init__ errread, errwrite) = self._get_handles(stdin, stdout, stderr) File "/usr/lib/python3.8/subprocess.py", line 1475, in _get_handles p2cread = stdin.fileno() AttributeError: 'bytes' object has no attribute 'fileno'
Nevermind, found the solution to this. I had to use the proc.communicate() to pass the data to the stdin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.