1

Currently calling:

f = open('/tmp/list.txt','w')
f.write(list)
f.close()  # Make sure to close the file before call sub-process.
           # Otherwise, file content will not visible to sub-process.

process = subprocess.Popen('oscommand --file={}'.format(f.name),
                           shell=True, stdout=subprocess.PIPE)

However need to use a variable as an argument which has been generated using [ShortId][1]. Need something like:

u=ShortId()
process = subprocess.Popen('oscommand --label "The unique id is "'+u' --file={}'.format(f.name),
                               shell=True, stdout=subprocess.PIPE)

How is the escaping best handled ?

2
  • Have you tried .format(str(u))? Commented Mar 29, 2016 at 13:23
  • You are passing a string to the Popen command. You can format the string and save it as a variable before you pass it in. Commented Mar 29, 2016 at 13:23

1 Answer 1

4

This is actually easier if you stop trying to make str commands with shell=True and just use the safer, faster list based command with shell=False (the default):

u=ShortId()
cmd = ['oscommand', '--label', 'The unique id is {}'.format(u), '--file={}'.format(f.name)]
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)

This avoids the risk of either the id or the file name containing shell metacharacters (say, a space) causing the command to be parsed incorrectly (or dangerously, if the string is actively malicious, e.g. a file named foo;sudo rm -rf /*).

Also note that there are better ways to do temporary files, whether or not the file is supposed to last after the Popen command finishes:

import tempfile

with tempfile.NamedTemporaryFile('w+t', delete=False) as f:
    f.write(mylist)
... rest of code here ...

Alternatively, if the file should be cleaned up automatically after use:

with tempfile.NamedTemporaryFile('w+t') as f:
    f.write(mylist)
    f.flush()
    ... rest of code using temp file ...
Sign up to request clarification or add additional context in comments.

8 Comments

Even the last argument can be split as two: [..., '--file', f.name]. The --arg=value form is intended for situations (not of which I can think of at the moment) where it is more convenient to think of the option and its argument as a single shell word.
@chepner: That would depend on the argument parsing library in use, but I agree that most would treat it equivalently.
Tried to switch over to using tempfile before proceding however following error when implementing as shown above by ShadowRanger "Problem reading file '/tmp/tmpULLmrW' "
@dross: Did you close or otherwise delete the Python reference to the tempfile before the Popen-ed program finished? If it doesn't open the file until after Python deletes it, that would cause problems.
@ShadowRange: If I try: with tempfile.NamedTemporaryFile('w+t') as f: f.write(subnets) f.seek(0) for line in f: print line.rstrip() f.close() Then I get only a partial output of lines until "Problem reading file /tmp/xxx" appears. The file has around 15,000 lines and it would appear to be getting discarded early.
|

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.