0

I've got a program which executes other python scripts depending on data it receives. The data it receives is in json format and can be helpful to those executed scripts.

This is why I want these scripts to receive the json somehow. I thought of doing it using the subprocess module using Popen but I don't think it'll work since I have to send an escaped string or a json object (after the json.loads() method). I can also write the json to a file and read it but that seems like poor choice.

So how do I achieve this elegantly?

matanc1
  • 6,525
  • 6
  • 37
  • 57

1 Answers1

3

If there will only be one sub-process at a time, and the parent will wait for the child to finish, you can just use Popen.communicate(). Example:

# Create child with a pipe to STDIN.
child = subprocess.Popen(..., stdin=subprocess.PIPE)

# Send JSON to child's STDIN.
# - WARNING: This will block the parent from doing anything else until the
#   child process finishes
child.communicate(json_str)

Then, in the sub-process (if it is python), you can read it with:

# Read JSON from STDIN.
json_str = sys.stdin.read()

Or, if you'd like a more complicated use where the parent can write multiple times to multiple sub-processes, then in the parent process:

# Create child with a pipe to STDIN.
child = subprocess.Popen(..., stdin=subprocess.PIPE)

# Serialize and send JSON as a single line (the default is no indentation).
json.dump(data, child.stdin)
child.stdin.write('\n')

# If you will not write any more to the child.
child.stdin.close()

Then, in the child you would read each line when desired:

# Read a line, process it, and do it again.
for json_line in sys.stdin:
    data = json.loads(json_line)
    # Handle received data.
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
  • Won't it be problematic since the json is escaped and so it'll read up until the first new line? – matanc1 Jun 06 '14 at 18:07
  • @Shookie That depends. If you do a whole `.read()` (waits for STDIN to be closed), the JSON can have as many new-lines as you want. If you want the JSON to be on only one line, you'll have to make sure the JSON is serialized without indentation and in which case you want to use `.readline()`. – Uyghur Lives Matter Jun 06 '14 at 18:13
  • I've done as you've said but I seem to get `childe_exception` thrown from `subprocess`. Could it be since my command is in the form of `python A/script.py`? Also, in the second example you gave, wouldn't it be `child.stdin` instead of `sys.stdin`? – matanc1 Jun 06 '14 at 18:47
  • @Shookie Can you put the whole exception in your question or look at [this](http://stackoverflow.com/q/11566967/369450) if that's what you're experiencing? Yes, it should be `child.stdin` not `sys.stdin`. – Uyghur Lives Matter Jun 06 '14 at 19:14