13

I have a script that calls os.execvp into another Python instance. After doing this, I appear to be attached to a cmd.exe instance, not the Python instance I just created. The Python instance responds to Ctrl+C however.

H:\bin>Python 3.2.1 (default, Jul 10 2011, 21:51:15) [MSC v.1500
 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print('hi')
Can't find file ('hi')

H:\bin>

H:\bin>
KeyboardInterrupt
>>> echo hi
hi

The call to exec:

from sys import argv
os.execvp('python', argv)

How do I replace the original Python instance with the new one, as per the behaviour one might see on Linux?

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
  • Related: http://bugs.python.org/issue9148. According to Amaury Forgeot d'Arc's [comment](http://bugs.python.org/issue9148#msg109179) - *on Windows, `exec()` does not really replace the current process. It creates a new process (with a new pid), and exits the current one. Hence the calling program only sees that the script has terminated. I don't see any easy solution on Windows, except than using `subprocess.Popen()`, and exit the script when the subprocess terminates.* Does it look like a possible solution in your case? – Piotr Dobrogost Aug 04 '13 at 13:49
  • Thanks for the useful comment @PiotrDobrogost. If you related the material in the Python issue to this question that would constitute a solution. – Matt Joiner Aug 04 '13 at 14:00
  • You mean like first calling `subprocess.Popen()` and then exiting from the original Python process? – Piotr Dobrogost Aug 04 '13 at 14:14
  • @PiotrDobrogost: Yes, in the interest of people following this same problem, they deserve a clean solution and justification. – Matt Joiner Aug 05 '13 at 02:38
  • @MattJoiner Hi, I just stumbled into this while trying to port a library to Windows. I am struggling to find a complete, working example based on `subprocess.Popen`. Any idea where I could find one? – s-m-e May 03 '21 at 13:13
  • @s-m-e sorry, no. – Matt Joiner May 04 '21 at 22:56

1 Answers1

4

On Unix executing binaries is split into two stages - fork(3) to clone current process and exec(3) to load executable into address space. On windows there is only CreateProcess which does the same thing as fork+exec.

For portability your best bet is to use subprocess.Popen (which also does proper filename quoting on Windows unlike os.* counterparts) as in http://docs.python.org/library/subprocess.html#replacing-the-os-spawn-family

Zart
  • 1,421
  • 10
  • 18
  • Can you link to a mention of the differing `os.exec*` behaviour on Windows? I was under the impression that exec is supported on Windows, see [here](http://msdn.microsoft.com/en-us/library/431x4c1w(v=VS.100).aspx) – Matt Joiner Aug 12 '11 at 10:45
  • First paragraph in url you posted: "Each function in this family loads and executes a *new* process". In MS CRT they're just wrappers around CreateProcess. – Zart Aug 12 '11 at 13:10
  • _When a call to an _exec function is successful, the new process is placed in the memory previously occupied by the calling process. Sufficient memory must be available for loading and executing the new process._ Also after the example exec call, there's a comment `/* This point is reached only if exec fails. */`. – Matt Joiner Aug 12 '11 at 13:23
  • I suspect that line was copied verbatim from POSIX.1 spec. "This point is reached": see description of any _exec, "Return value" clause. "If successful, these functions do not return to the calling process", they do ExitProcess() call upon sucessful CreateProcess() call iirc. – Zart Aug 12 '11 at 13:56
  • For detailed information on how CreateProcess works internally see http://www.scribd.com/doc/51979000/122/Flow-of-CreateProcess – Zart Aug 12 '11 at 14:05
  • that line was from the MSDN documentation. – Matt Joiner Aug 21 '11 at 04:24