This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: subprocess throws wrong exception if script can't be executed
Type: behavior Stage: resolved
Components: None Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Cal.Leeming, gregory.p.smith, neologix, r.david.murray
Priority: normal Keywords:

Created on 2011-06-01 15:26 by Cal.Leeming, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (8)
msg137439 - (view) Author: Cal Leeming (Cal.Leeming) Date: 2011-06-01 15:26
If you attempt to call subprocess.check_output() on a file which is not executable, it gives a "file not found" exception, rather than "file not executable". Took me about 3 hours to figure out why it kept saying the file didn't exist, when it clearly did :|


 ***@***# ls -la ***/src/webapp/tools/grab.sh
-rwxr-xr-x 1 *** *** 4398 Apr 19 10:55 ***/src/webapp/tools/grab.sh

 ***@***# ***/src/webapp/tools/grab.sh
bash: ***/src/webapp/tools/grab.sh: /bin/sh^M: bad interpreter: No such file or directory


Traceback (most recent call last):

  File "***/src/webapp/../webapp/idx/fourchan/tasks.py", line 77, in run
    subprocess.check_output([ DOWNLOAD_BIN, ])

  File "/usr/local/lib/python2.7/subprocess.py", line 530, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)

  File "/usr/local/lib/python2.7/subprocess.py", line 672, in __init__
    errread, errwrite)

  File "/usr/local/lib/python2.7/subprocess.py", line 1201, in _execute_child
    raise child_exception

OSError: [Errno 2] No such file or directory


Request:
None
msg137440 - (view) Author: Cal Leeming (Cal.Leeming) Date: 2011-06-01 15:28
Oh also, here is the version:


 simplicitymedialtd@sws01.internal [~/webapps/cdn06.prod/src/webapp/cmd] > python
Python 2.7 Stackless 3.1b3 060516 (release27-maint, Aug 29 2010, 15:44:48)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
msg137441 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-06-01 16:49
Python is not raising this error, your OS is.
It doesn't find the interpreter, and if you look carefully, it's clear why:

bash: ***/src/webapp/tools/grab.sh: /bin/sh^M: bad interpreter: No such file or directory

See the ^M after /bin/sh?
It's looks like a DOS line ending, and the spurious \r character is concatenated to the intepreter path, leading to this error.
You didn't copy this script through a Windows box, didn't you?
Just run dos2unix on your script, and it should solve your problem.
msg137442 - (view) Author: Cal Leeming (Cal.Leeming) Date: 2011-06-01 16:57
Yeah, I resolved the issue already. This bug report is focused primarily on the (somewhat misleading) exception message given back.  

I think it should at least include "bad interpreter", otherwise it is a tad misleading.

Cal
msg137443 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2011-06-01 17:19
Subprocess is throwing the correct exception, what it isn't doing is preserving stderr.  The stderr output in question is not coming from the *subprocess* (the process hasn't been created yet).  It would be nice if that stderr output could be added to the exception message, but that is not normally the way os errors are handled in python.
msg137445 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-06-01 17:34
> I think it should at least include "bad interpreter", otherwise it is a tad misleading.

It just forwards the error raised by the exec system call:

$ cat foo.sh 
#! /bin/foo
$ strace ./foo.sh 
execve("./foo.sh", ["./foo.sh"], [/* 38 vars */]) = -1 ENOENT (No such file or directory)

> Subprocess is throwing the correct exception, what it isn't doing is preserving stderr.

There's not stderr, it's just execve which is failing with errno set to ENOENT.
Now, if you wonder how bash manages to print this "bad interpreter" error message, it's simple: it first checks for common errno values (ENOEXEC, ENOMEM), and then it parses the shebang: if it finds a line starting with #!, it assumes that it's a bad interpreter, and prints the offending line.
That's it.

Suggesting to close as invalid.
msg137450 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2011-06-01 17:54
Ah, I see.  Agreed with the closing, then.

Cal: one way to debug this kind of thing is to try the same command with shell=True.  Then the shell will generate its special error message.

Changing the title back to something that might be recognizable to others who run into this problem.
msg137451 - (view) Author: Cal Leeming (Cal.Leeming) Date: 2011-06-01 17:56
Ah okay, shell=True is a good work around then :)

Thanks!

Cal
History
Date User Action Args
2022-04-11 14:57:18adminsetgithub: 56444
2011-06-01 17:56:59Cal.Leemingsetmessages: + msg137451
2011-06-01 17:54:27r.david.murraysetstatus: open -> closed
title: subprocess loses stderr information when _execute_child fails -> subprocess throws wrong exception if script can't be executed
messages: + msg137450

resolution: not a bug
stage: resolved
2011-06-01 17:34:47neologixsetmessages: + msg137445
2011-06-01 17:19:37r.david.murraysetnosy: + gregory.p.smith, r.david.murray
title: subprocess.check_output throws wrong exception if non executable -> subprocess loses stderr information when _execute_child fails
messages: + msg137443

versions: + Python 3.2, Python 3.3
2011-06-01 16:57:05Cal.Leemingsetmessages: + msg137442
2011-06-01 16:49:24neologixsetnosy: + neologix
messages: + msg137441
2011-06-01 15:28:00Cal.Leemingsettype: behavior
messages: + msg137440
components: + None
versions: + Python 2.7
2011-06-01 15:26:36Cal.Leemingcreate