2

In the script I've attached below I'm attempting a pretty simple process using Python. Sequential execution of native Windows commands as well as calling executables from Freeware, portable programs. The subprocess.call() function isn't operating as expected though.

Behavior I'm experiencing:

~ The ONE variable gets called and then stops/waits, like I expect it to, but when I exit out of ONE (taskmgr) it starts TWO and THREE simultaneously and then waits.

~ When I exit THREE it calls the two portable programs, FOUR and FIVE, simultaneously and waits.

~ It then starts SIX and waits.

~ Finally it executes the rest of the commands simultaneously without pausing.

Any explanations for the cause of this behavior? And/or suggested work arounds for accomplishing the same results?

import subprocess

def AutoCommands():
    ONE = 'taskmgr /0 /startup'
    TWO = 'taskschd.msc'
    THREE = 'services.msc'
    FOUR = '"%CD%/FolderDirectory/PortableProgram" -custom -flags'
    FIVE = '"%CD%/FolderDirectory/PortableProgram2" -more -flags'
    SIX = '"%CD%/FolderDirectory/PortableProgram3" -more -flags'
    SEVEN = '"appwiz.cpl"'
    EIGHT = 'wuapp'

    autocommands = [ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT]

    for command in autocommands:
        subprocess.call(command, shell=True)

AutoCommands()

EDIT: I expect/want each command to be executed but not moving onto the next command until the current one has been cancelled/killed. Similar to using start /wait program.exe && program2.exe, etc... I've written the above script in .bat and it runs as you would expect, waiting in between commands. However if I try executing that .bat using os.system() or subprocess.Popen() it exhibits the same behavior. If I try directly using os.system("start /wait program.exe && start /wait program2.exe") it's exhibits the same behavior.

I've also tried the suggestion here using subprocess.Popen (not what I want to use) but couldn't get that to work at all.

Community
  • 1
  • 1
  • 2
    Print the return code from subprocess.call; make sure they aren't hitting errors. – hazydev May 27 '15 at 18:36
  • What happens if you run exactly the same commands manually in Windows console. Do you expect different results if you run the commands from Python? Run: `subprocess.check_call("\n".join(autocommands), shell=True)` (if it fails try `"; "` or `" & "` instead of `"\n"`). – jfs May 28 '15 at 07:15
  • When I execute the commands manually, it does what I would like it to. Yes I expect different results when running in Python because of the `.call()` function. I expect it to execute a command and wait for that command to be cancelled/exited. Similar to using `start /wait commandhere` or using `&&`, etc... I even tried making a `.bat` file with the above script example and it worked fine (waiting in between commands) however even when I open the `.bat` using `os.system(./batchfile.bat)` or `subprocess.Popen(./batchfile.bat)` it has the same initial behavior mentioned in the question. –  May 28 '15 at 14:48
  • Also the command you suggested just puts the specified character in between each letter of each command and returns a "non zero exit status" –  May 28 '15 at 14:53
  • 1
    @BiTinerary: 1. if the command doesn't return immediately when you run it manually then it won't return at once in Python too (if you use `check_call()`). 2. *"puts the specified character in between each letter"* -- no, it won't. `autocommands` is a **list**: `" & ".join(["1st", "2nd"])` -> `"1st & 2nd"`. My best guess is that your commands *fail to start* that is why you see them to return immediately that is why I've suggested `check_call()` that raises an exception instead of ignoring the error silently. – jfs May 29 '15 at 09:23
  • @JF Sebastian. 1. You or I are simply confused as to our understandings on this one. Perhaps I just don't make sense to anyone (my bad) but I've been able to run it (as expected) in CMD, it's not unreasonable to expect the same results in Python. 2. Yes, it will because it did. I ran the "&".join() and that's what it **did**, I wasn't just speculating when I said that, I understand what you're suggesting to do but it's not separating the **list** but rather the strings (commands) in the list. I've also tried check_call() I'll come back later when I've tried all this over again. Thanks. –  May 29 '15 at 13:30
  • 1. Yes. It should behave the same in Python that is the point. 2. No. What happens if you copy-paste the expression as is **exactly** as it is shown in [my comment](http://stackoverflow.com/questions/30490452/erratic-behavior-when-using-subprocess-call-within-a-for-loop-python#comment49075667_30490452): [`"\n".join(autocommands)`](http://ideone.com/hpDOB0) (`cmd.exe` probably doesn't support a multiline input or it had to be escaped. It is probably simpler to save the string into a batch file. btw, you don't need `shell=True` to run a batch file). To wait, use `check_call()`, not `Popen()`. – jfs May 30 '15 at 18:18

0 Answers0