SuperBiasedMan
SuperBiasedMan

Reputation: 9969

How to determine what string subprocess is passing to the commandline?

On Windows, you make a subprocess call by passing a list of string arguments that it then reformats as a single string to call the relevant command. It does this by a series of rules as outline in the documentation here.

On Windows, an args sequence is converted to a string that can be parsed using the following rules (which correspond to the rules used by the MS C runtime):

  1. Arguments are delimited by white space, which is either a space or a tab.
  2. A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.
  3. A double quotation mark preceded by a backslash is interpreted as a literal double quotation mark.
  4. Backslashes are interpreted literally, unless they immediately precede a double quotation mark.
  5. If backslashes immediately precede a double quotation mark, every pair of backslashes is interpreted as a literal backslash. If the number of backslashes is odd, the last backslash escapes the next double quotation mark as described in rule

However in practice this can be hard to get right, as it's unclear exactly how the strings are being interpreted. And there can be trial and error in figuring out how to properly format the command.

Is there a way I can just determine what string subprocess would formulate? That way I can inspect it and ensure it's being formulated correctly as well as logging it better than just logging the list form of the command.

Upvotes: 3

Views: 116

Answers (1)

SuperBiasedMan
SuperBiasedMan

Reputation: 9969

I dug into the actual subprocess module and found an answer in there in fact. There's a function called list2cmdline that's used to just take a list passed to Popen and turn it into a single string of commandline arguments. It can just be called on with the list to get the result I need:

import subprocess

name = "Monty Python's Flying Circus"
path = r"C:\path\to\files"
subprocess.list2cmdline(["file.py", name, path])
# 'file.py "Monty Python\'s Flying Circus" C:\\path\\to\\files'

Upvotes: 5

Related Questions