3

I'm using subprocess.Popen to launch an external program with arguments, but when I've opened it the script is hanging, waiting for the program to finish and if I close the script the program immediately quits.

I thought I was just using a similar process before without issue, so I'm unsure if I've actually done it wrong or I'm misremembering what Popen can do. This is how I'm calling my command:

    subprocess.Popen(["rv", rvFile, '-nc'])
    raw_input("= Opened file")

The raw_input part is only there so the user has a chance to see the message and know that the file should be opened now. But what I end up getting is all the information that the process itself is spitting back out as if it were called in the command line directly. My understanding was that Popen made it an independent child process that would allow me to close the script and leave the other process open.

The linked duplicate question does have a useful answer for my purposes, though it's still not working as I want it.

This is the answer. And this is how I changed my code:

DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen(["rv", rvFile, '-nc'], creationflags=DETACHED_PROCESS).pid
raw_input("= Opened file")

It works from IDLE but not when I run the py file through the command prompt style interface. It's still tied to that window, printing the output and quitting the program as soon as I've run the script.

Community
  • 1
  • 1
SuperBiasedMan
  • 9,814
  • 10
  • 45
  • 73
  • 1
    possible duplicate of [Calling an external command in Python](http://stackoverflow.com/questions/89228/calling-an-external-command-in-python) – Matt Seymour May 05 '15 at 11:50
  • If you think you found a solution; don't put it in your *question*. Post it as an answer instead (to allow independent commenting, voting, jumping directly to answers). – jfs May 09 '15 at 17:38
  • You should probably redirect `stdin`, `stdout`, `stderr` (to [`DEVNULL`](http://stackoverflow.com/q/11269575/4279) if you want to ignore the output) – jfs May 09 '15 at 17:39
  • 1
    related: [Python: Howto launch a full process not a child process and retrieve the PID](http://stackoverflow.com/q/14797236/4279) – jfs May 09 '15 at 17:43
  • @J.F.Sebastian I might not have made it clear enough, but the answer I was linking to didn't sufficiently solve my problem, that said I did solve it by combining answers and I should answer with that now, thanks for the reminder! – SuperBiasedMan May 11 '15 at 07:22

3 Answers3

1

The stackoverflow question Calling an external command in python has a lot of useful answers which are related.

Take a look at os.spawnl, it can take a number of mode flags which include NOWAIT, WAIT.

import os
os.spawnl(os.P_NOWAIT, 'some command')

The NOWAIT option will return the process ID of the spawned task.

Community
  • 1
  • 1
Matt Seymour
  • 8,880
  • 7
  • 60
  • 101
1

Sorry for such a short answer but I have not earned enough points to leave comments yet. Anyhow, put the raw_input("= Opened file") inside the file you are actually opening, rather than the program you are opening it from.

If the file you are opening is not a python file, then it will close upon finishing,regardless of what you declare from within python. If that is the case you could always try detaching it from it's parent using:

from subprocess import Popen, CREATE_NEW_PROCESS_GROUP
subprocess.Popen(["rv", rvFile, '-nc'], close_fds = True | CREATE_NEW_PROCESS_GROUP)
ajsp
  • 2,512
  • 22
  • 34
  • The file is actually in a different program. The script basically compiles a list of videos into a filetype and then opens that in a particular program. This solution again worked in IDLE but not the Command Prompt. I'm starting to wonder if the program that I'm opening could be the problem. – SuperBiasedMan May 05 '15 at 13:47
  • 1
    If I read you right you want to close the spawned process independently? For that you will need to create a new shell, shell = True. If the solution works in IDLE, it won't be your script, and you can be sure the code is correct. How are you running the command prompt? Is it from the windows scheduler by any chance? (Also, get rid of the raw_input) – ajsp May 05 '15 at 14:11
  • It's a manual run of the python file, basically double clicking the python file in Windows. But using the combination of DETACHED_PROCESS and the shell did exactly what I wanted, it allows me to close the python script window and leave the other program still running. Thanks! – SuperBiasedMan May 05 '15 at 14:20
0

This is specifically for running the python script as a commandline process, but I eventually got this working by combining two answers that people suggested.

Using the combination of DETACHED_PROCESS suggested in this answer worked for running it through IDLE, but the commandline interface. But using shell=True (as ajsp suggested) and the DETACHED_PROCESS parameter it allows me to close the python script window and leave the other program still running.

DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen(["rv", rvFile, '-nc'], creationflags=DETACHED_PROCESS, shell=True).pid
raw_input("= Opened file")
Community
  • 1
  • 1
SuperBiasedMan
  • 9,814
  • 10
  • 45
  • 73
  • avoiding "python script window" looks like a different issue (you could use `.pyw` file extension or run your script using `pythonw.exe` explicitly). You should add `close_fds=True` (or redirect all stdin,stdout,stderr) and get rid of `shell=True`. – jfs May 11 '15 at 10:02
  • creationflags is only supported on Windows platform. (that's the error I got for python3.X) – deelaws May 17 '18 at 20:29