0

I am using popen to run the following command on a windows vm

'tf changeset ...'

however when I run it using

commandLine = 'tf changeset /noprompt /latest /loginType:OAuth /login:.,***'

process = Popen(commandLine, shell=True, stdout=PIPE, stderr=PIPE)

I see the following being executed in the logs

'C:\Azure\Agent-1/externals/tf/tf changeset ...'

Meaning that 'C:\Azure\Agent-1/externals/tf/' has been prepended to my command. I was just expecting to see

'tf changeset ...'

Unfortunately adding the path to the execution breaks the command, is there any way to stop python from doing this?

James
  • 589
  • 1
  • 6
  • 15
  • How do you add the path ? – Maurice Meyer Jul 07 '21 at 11:51
  • Sorry Maurice not sure what you mean, I am not adding the path. I expected to see in the logs the following being executed: 'tf changeset ...' but instead see 'C:\Azure\Agent-1/externals/tf/tf changeset ...' – James Jul 07 '21 at 11:58

2 Answers2

1

Try passing the commandLine to Popen as a list of arguments:

commandLine = ["tf", "changeset", "/noprompt", "/latest", "/loginType:OAuth", "/login:.,***'"]
process = Popen(commandLine, stdout=PIPE, stderr=PIPE)
Deneb
  • 981
  • 2
  • 9
  • 25
  • I thought when using Popen on windows with shell=True you should pass everything as a string? – James Jul 07 '21 at 12:15
  • 1
    As per the documentation, you should beasically never need `shell=True` on Windows (either). – tripleee Jul 07 '21 at 12:16
1

Python by itself does no such thing. Perhaps the shell=True is doing more than you hoped or bargained for? But we would need access to your shell's configuration to get beyond mere speculation around this.

Calling Popen on the result from Popen is obviously not well-defined; but perhaps this is just an error in your transcription of your real code?

Removing the first process =Popen( would fix this with minimal changes. As per the above, I would also remove shell=True as at least superfluous and at worst directly harmful.

commandLine = 'tf changeset /noprompt /latest /loginType:OAuth /login:.,***'
process = Popen(commandLine, stdout=PIPE, stderr=PIPE)

Like the subprocess documentation tells you, shell=True is only useful on Windows when your command is a cmd built-in.

For proper portability, you should break the command into tokens, manually or by way of shlex.split() if you are lazy or need the user to pass in a string to execute.

commandLine = ['tf ', 'changeset', '/noprompt', '/latest', '/loginType:OAuth', '/login:.,***']
process = Popen(commandLine, stdout=PIPE, stderr=PIPE)

This avoids the other dangers of shell=True and will be portable to non-Windows platforms (assuming of course that the command you are trying to run is available on the target platform).

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Apologies triplee the additional process=Popen was a copy paste mistake. I've amended the question. I will look into shell=True, appreciate the answer. – James Jul 07 '21 at 12:39