On Sat, Oct 15, 2016 at 8:12 PM, Stephen R. van den Berg <s...@cuci.nl> wrote: > Chris Angelico wrote: >>Two features added to the Process module. Firstly, a simple wrapper >>Process.check_run that calls Process.run and throws an error if the >>exit code isn't 0; > > This is a bit overkill, I'd say. It's not generic enough to put in the > lib. What if you want to check for a certain range of exitcodes instead? > If you want this, I'd say you inherit the class and add your own convenience > functions to it, but at application level.
There's a strong convention that zero == success, nonzero == failure, so this would apply as-is to a lot of programs. Obviously this shouldn't be the one and only way to run a subprocess (this is NOT a proposed change to Process.run, it's a separate function), so if you want to invoke grep(1) and accept 0 (lines found) and 1 (no lines found) but not 2 (error), then you'd make an app-specific function; but 0 vs other is common enough that I think this fits the standard library. Example of prior art: Python's subprocess.check_call and check_output functions raise an exception on non-zero return value: https://docs.python.org/3/library/subprocess.html#subprocess.CalledProcessError >> and secondly, a means for Process.run() to leave >>stderr attached to the console. The intention is for this to be used > > That seems useful, so I'd welcome that. > But then support it for stdout too. > Then again, maybe this is better off generalised, into requiring/allowing > you to specify things like: > > ({"stdout":Stdio.stdout, "stderr":Stdio.stderr}) > > instead of the magic "-". > > This would support adding different objects too, in order to redirect > directly into a file or some other pipe. If you don't want to redirect either, or if you want to redirect them both to files, use Process.Process or Process.create_process directly. The advantage of Process.run is that it captures the output. I suppose you might conceivably want to capture stderr but leave stdout attached to the console, but it's a lot less common than "run program, give it input, retrieve output, but if it displays an error, let that be seen". I can't think of any use-cases for the converse. Process.run() is great, but there are a lot of times when I have to either replicate half of its code, or use run() and risk squashing an unexpected error. With check_run, I'd be able to have virtually the same API, but with the declaration that a program error is an exception. Consider a simple way to get audio file information: string info = Process.run(({"soxi", "audio_01.wav"}))->stdout; //proceed to parse the given info, eg: sscanf(info, "%*[\n]%{%s: %s\n%}", array lines); mapping fields = (mapping)lines; If soxi is not available, this will raise an immediate exception, rather than charging on blindly; but if audio_01.wav isn't found, there's no indication of the actual problem - you just don't get any useful output. Using check_run causes an instant failure, saying that the process exited 1; and keeping stderr attached to the console would let the user see the message from soxi: string info = Process.check_run(({"soxi", "audio_01.wav"}), (["stderr": "-"]))->stdout; In fact, this usage could itself be wrapped up another level, if desired. I've tossed another commit onto the branch to add a check_output function, but this one is less significant (it's just a one-liner). With check_output, omitting the modifiers mapping gives the natural and obvious behaviour of the above line of code. ChrisA