[lug] Python: Unable to catch subprocess error
Lee Woodworth
blug-mail at duboulder.com
Sat Mar 10 21:05:37 MST 2018
On 03/10/2018 10:10 AM, Jed S. Baer wrote:
> On Sat, 10 Mar 2018 07:51:47 -0700
> Rob Nagler wrote:
>
>> It's why I say programming in Python is like being inside a Monty Python
>> sketch. You never know what's going to happen next, and none of it makes
>> any sense, but if you keep your sense of humor about you, it's a barrel
>> of laughs! ....
Now if I could only get paid for a barrel of laughs.
> I appreciate the followup, and I hope it was at least as enjoyable as
> watching Brazil. As much as I like that movie, it doesn't represent the
> experience I'm looking for when trying to write code.
If the OP is interested in other approaches to exception/error handling, go
could be worth a look.
I don't know anything about python but it sounds like go's handling of error
indication, clean up and exceptions is pretty different.
A go example showing some common idioms:
1 func ThingFromFile (path string, config *Config) (*TheThing, error) {
2 if config == nil { panic ("nil config") }
3 theFile, err := os.Open (path)
4 if err != nil {
6 if err == os.ErrNotExist {
7 return nil, errors.New ("thing file missing")
8 }
9 return nil, err
10 }
11 defer theFile.Close ()
12 if err := config.CheckFile (theFile); err != nil {
13 return err
14 }
15 config.Lock (); defer config.Unlock ()
16 ... do stuff and set result ...
17 return result, nil
18 }
[ NOTE declarations are <NAME> <TYPE>, ThingFromFile returns two values with
types *TheThing and error ]
In go, errors, exceptional situations (e.g. programmer errors) and clean up
are separate. Philosophically, exceptions are for things like the world is on
fire, like line 2. Note there is no try statement to make sure the file is
closed and the lock released. error is a standard type and functions that can
report errors return a value of that type (generating exceptions for errors is
not recommended practice). A common idiom is line 3 where the file "handle" and
the error are provided by open's multiple return values.
The funky defer statements in lines 11 and 15 provide the cleanup on success
and failure. They don't execute immediately but just before the function exits
via a return statement or a stack unwind due to an exception. config.Unlock ()
won't be scheduled until execution reaches line 15. So you don't have to keep
track of state to know what has to be cleaned up. IIRC the java I did many years
ago required logic in the finally blocks to figure out what resources/locks were
successfully allocated/acquired to prevent releasing/unlocking something that
wasn't there/owned.
At first having to do things like lines 12-14 seemed like a pain. For me, the
consistency in error reporting and the simplicity of clean up make up for the
repetition.
I'm not a go expert. I've only been using the language for about 3 years and my
ADD kicks in when I read the language spec section on name visibility for embedded
types. So you should probably take this with a salt shaker.
p.s. error is an interface so you can create your own error types.
More information about the LUG
mailing list