Python subprocess fails, depending on how IDLE is opened
On a MacBook Pro with Mac OS X version 10.6.7, I have a simple python script 'test.py':
import subprocess
subprocess.Popen(['xterm'])
If I run this script by opening it in IDLE using the mouse, it crashes. If I run the same script in an IDLE that I launch by typing 'idle' in a terminal, it doesn't crash. What's going on?
Details:
Launch IDLE by right clicking test.py and "open with" IDLE (2.6.6). It only opens the Python Shell and IDLE, not test.py. I open test.py and select "run module" from the "Run" menu. Pasted below is the contents from the Python Shell. Included at the bottom is the sys.path for IDLE opened in this manner.
Python 2.6.6 (r266:84292, May 11 2011, 21:44:06)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "copyright", "credits" or "license()" for more information.
****************************************************************
Personal firewall software may warn about the connection IDLE
makes to its subprocess using this computer's internal loopback
interface. This connection is not visible on any external
interface and no data is sent to or received from the Internet.
****************************************************************
IDLE 2.6.6
>>> ================================ RESTART ================================
>>>
Traceback (most recent call last):
File "/Users/georgepatterson/test.py", line 2, in <module>
subprocess.Popen(['xterm'])
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 623, in __init__
errread, errwrite)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 1141, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
>>> import sys
>>> for p in sys.path: print p
/Users/georgepatterson
/Users/georgepatterson/Documents
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python26.zip
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-darwin
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac/lib-scriptpackages
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-old
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/PyObjC
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python开发者_运维技巧2.6/site-packages/setuptools-0.6c11-py2.6.egg-info
>>>
Launch IDLE through a terminal window. Open test.py and select "run module" from the "Run" menu. When run in this manner, the terminal window is opened properly. I've pasted the contents of the Python Shell below with the sys.path also.
Python 2.6.6 (r266:84292, May 11 2011, 21:44:06)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "copyright", "credits" or "license()" for more information.
****************************************************************
Personal firewall software may warn about the connection IDLE
makes to its subprocess using this computer's internal loopback
interface. This connection is not visible on any external
interface and no data is sent to or received from the Internet.
****************************************************************
IDLE 2.6.6
>>> ================================ RESTART ================================
>>>
>>> import sys
>>> for p in sys.path: print p
/Users/georgepatterson
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/bin
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python26.zip
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-darwin
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac/lib-scriptpackages
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-old
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/PyObjC
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg-info
>>>
The difference in behavior you are seeing does indeed have to do with the PATH
environment variable. When you start IDLE via a terminal shell, it inherits the PATH
value from your shell environment. path_helper(8)
sets the default value for a login shell PATH
by consulting the entries in /etc/paths.d/
. On OS X 10.6, that includes /usr/X11/bin
, which is where xterm is located. However, when you launch IDLE from the Finder, either by double-clicking on the IDLE app icon or by opening a file using IDLE as the default app (as you are doing in test 1), a shell is not involved and the PATH
inherited by the app environment is slightly different. In paticular, /etc/paths.d
is not consulted and so /usr/X11/bin
is not on the path. You should be able to see that by looking at PATH
in both cases. For IDLE.app launched from the Finder, you'll probably see something like:
>>> os.environ['PATH']
'/usr/bin:/bin:/usr/sbin:/sbin'
While it is possible to change the default environment variables for processes launched, it is rarely necessary or desirable to do that. For this case, the simplest solution is to supply the absolute path to xterm
:
import subprocess
subprocess.Popen(['/usr/X11/bin/xterm'])
Or you could get fancier by modifying PATH yourself.
sys.path
is not relevant here (it's used to import python modules).
You should check the PATH environment variable: os.environ['PATH']
.
It's probable that the OS X terminal installs some additional paths.
精彩评论