Repository: ipython/ipython

Issue:
_subprocess module removed in Python 3.3
In Python 3.3, there is no _subprocess, thus a couple of IPython.zmq related methods fail due missing import on Windows. The items imported were Windows specific API calls that the subprocess module used privately on Windows. The API calls are available via [pywin32](http://sourceforge.net/projects/pywin32/) (specifically from win32api, win32con and win32event modules), however that currently doesn't have a released version that works for Python 3.3, although current tip/trunk does work. Below is a patch which fixes the issue for Python 3.3 and likely works for the other versions of Python as well. The question is which of the following would be most preferable:
1. should a dependency be added on pywin32 for just Python 3.3
2. move away from the private _subprocess include for all versions and have pywin32 be a dependency for IPython on Windows, or
3. find a mechanism, if possible, that removes the need for _subprocess or pywin32

_There is already a dependency on pywin32, at least in some contexts (Parallel/HPC, others?), so it would seem that long-term, **2** is probably preferable._

``` diff
diff --git a/IPython/zmq/entry_point.py b/IPython/zmq/entry_point.py
index dff9286..960fccb 100644
--- a/IPython/zmq/entry_point.py
+++ b/IPython/zmq/entry_point.py
@@ -189,8 +189,8 @@ def base_launch_kernel(code, fname, stdin=None, stdout=None, stderr=None,
                          creationflags=512, # CREATE_NEW_PROCESS_GROUP
                          stdin=_stdin, stdout=_stdout, stderr=_stderr)
         else:
-            from _subprocess import DuplicateHandle, GetCurrentProcess, \
-                DUPLICATE_SAME_ACCESS
+            from win32api import DuplicateHandle, GetCurrentProcess
+            from win32con import DUPLICATE_SAME_ACCESS
             pid = GetCurrentProcess()
             handle = DuplicateHandle(pid, pid, pid, 0,
                                      True, # Inheritable by new processes.
diff --git a/IPython/zmq/parentpoller.py b/IPython/zmq/parentpoller.py
index 5cf0b57..80f509b 100644
--- a/IPython/zmq/parentpoller.py
+++ b/IPython/zmq/parentpoller.py
@@ -100,7 +100,8 @@ def send_interrupt(interrupt_handle):
     def run(self):
         """ Run the poll loop. This method never returns.
         """
-        from _subprocess import WAIT_OBJECT_0, INFINITE
+        from win32con import WAIT_OBJECT_0
+        from win32event import INFINITE

         # Build the list of handle to listen on.
         handles = []
```



Discussion:
[it looks like](http://bugs.python.org/issue11750) the shortest route is to use the new `_winapi` module, which consolidated some scattered names.


Resolving patch:
diff --git a/IPython/zmq/entry_point.py b/IPython/zmq/entry_point.py
--- a/IPython/zmq/entry_point.py
+++ b/IPython/zmq/entry_point.py
@@ -189,8 +189,12 @@ def base_launch_kernel(code, fname, stdin=None, stdout=None, stderr=None,
                          creationflags=512, # CREATE_NEW_PROCESS_GROUP
                          stdin=_stdin, stdout=_stdout, stderr=_stderr)
         else:
-            from _subprocess import DuplicateHandle, GetCurrentProcess, \
-                DUPLICATE_SAME_ACCESS
+            try:
+                from _winapi import DuplicateHandle, GetCurrentProcess, \
+                    DUPLICATE_SAME_ACCESS
+            except:
+                from _subprocess import DuplicateHandle, GetCurrentProcess, \
+                    DUPLICATE_SAME_ACCESS
             pid = GetCurrentProcess()
             handle = DuplicateHandle(pid, pid, pid, 0,
                                      True, # Inheritable by new processes.
diff --git a/IPython/zmq/parentpoller.py b/IPython/zmq/parentpoller.py
--- a/IPython/zmq/parentpoller.py
+++ b/IPython/zmq/parentpoller.py
@@ -100,7 +100,10 @@ def send_interrupt(interrupt_handle):
     def run(self):
         """ Run the poll loop. This method never returns.
         """
-        from _subprocess import WAIT_OBJECT_0, INFINITE
+        try:
+            from _winapi import WAIT_OBJECT_0, INFINITE
+        except ImportError:
+            from _subprocess import WAIT_OBJECT_0, INFINITE
 
         # Build the list of handle to listen on.
         handles = []


Test patch: