5

I've search a while and still can not figure it out... Here's part of my code that went wrong.

import subprocess as sp
import os
cmd_args = []
cmd_args.append('start ')
cmd_args.append('/wait ')
cmd_args.append(os.path.join(dirpath,filename))
print(cmd_args)
child = sp.Popen(cmd_args)

And the command prompt through out this.

['start ', '/wait ', 'C:\\Users\\xxx\\Desktop\\directory\\myexecutable.EXE']
Traceback (most recent call last):
  File "InstallALL.py", line 89, in <module>
    child = sp.Popen(cmd_args)
  File "C:\Python34\lib\subprocess.py", line 859, in __init__
    restore_signals, start_new_session)
  File "C:\Python34\lib\subprocess.py", line 1114, in _execute_child startupinfo)
FileNotFoundError: [WinError 2]

It looks like the filepath is wrong with 2 backslashes.

I know if I do

print(os.path.join(dirpath,filename))

It'll return

C:\Users\xxx\Desktop\directory\myexecutable.EXE

I'm sure the file is there. How can I debug this?

user2869934
  • 931
  • 3
  • 8
  • 17
  • 1
    The first backslash is needed to escape the second backslash so the double backslash is not the issue – Farhan.K Sep 01 '16 at 10:59
  • Can you try to pass `shell=True` as well? – Idos Sep 01 '16 at 11:00
  • The path is correct. The double backslashes are not the issue, they are an artifact of the `repr` for strings. In any case: are you sure that the problem is the last argument and not the `start`? Is `start` a *command* or a shell built-in? – Bakuriu Sep 01 '16 at 11:04
  • 1
    @Idos Note that just adding `shell=True` wont produce the expected result. You have to use a single string argument to represent the command line, not the list of arguments when passing `shell=True`, i.e. `Popen('start /wait ', shell=True)`. – Bakuriu Sep 01 '16 at 11:05
  • Thanks a lot guys. Bakuriu's answer worked. Indeed I should pass my argument as string not list. – user2869934 Sep 02 '16 at 01:53

2 Answers2

4

This is happening because Popen is trying to find the file start instead of the file you want to run.

For example, using notepad.exe:

>>> import subprocess
>>> subprocess.Popen(['C:\\Windows\\System32\\notepad.exe', '/A', 'randomfile.txt']) # '/A' is a command line option
<subprocess.Popen object at 0x03970810>

This works fine. But if I put the path at the end of the list:

>>> subprocess.Popen(['/A', 'randomfile.txt', 'C:\\Windows\\System32\\notepad.exe'])
Traceback (most recent call last):
  File "<pyshell#53>", line 1, in <module>
    subprocess.Popen(['/A', 'randomfile.txt', 'C:\\Windows\\System32\\notepad.exe'])
  File "C:\python35\lib\subprocess.py", line 950, in __init__
    restore_signals, start_new_session)
  File "C:\python35\lib\subprocess.py", line 1220, in _execute_child
    startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified

Use this instead:

import subprocess as sp
import os
cmd_args = []
cmd_args.append(os.path.join(dirpath,filename))
cmd_args.append('start ')
cmd_args.append('/wait ')
print(cmd_args)
child = sp.Popen(cmd_args)

You might need to swap cmd_args.append('start ') and cmd_args.append('/wait ') around too depending on which order they are meant to be in.

Farhan.K
  • 3,164
  • 1
  • 14
  • 23
1

I faced the same problem and just to add a note about Popen: As argument Popen takes a list of strings for non-shell calls and only a string for shell calls.

Details listed here: WinError 2 The system cannot find the file specified (Python)