tomerfiliba / plumbum

Plumbum: Shell Combinators
https://plumbum.readthedocs.io
MIT License
2.82k stars 184 forks source link

plumbum.commands.processes.ProcessExecutionError doesn't capture stderr #359

Open rugubara opened 6 years ago

rugubara commented 6 years ago

I work with zfs command, it returns a generic 13 error code on many occasions when it can't create a dataset. All interesting details are printed to stderr and the exception doesn't capture it.

henryiii commented 6 years ago

It is supposed to. Looks like both are being captured:

https://github.com/tomerfiliba/plumbum/blob/46da89d8b2c53c2c6bf3ee30f7e013a326af219b/plumbum/commands/processes.py#L60-L84

Can you give a little example, better yet in test form so that it can be added to the tests and fixed if needed?

rugubara commented 6 years ago

I'll do my best to analyse and reproduce it. It seems that I'm running a pipe (self.cmdZfs['send','-c',snapshots[-1]] | destDS.cmdZfs['receive', '-vF', xcanmount, '-xcom.sun:auto-snapshot', destDS])() and the first process fails, produces its own stderr and closes the pipe. The second process fails due to premature stdin pipe closure and also terminates with a failure and reports broken pipe to the stdout.

I can't see the stderr of the second process in the exception, the stdout is very generic, not telling me a bit of the real issue encountered.

How can I capture the exception (and stderr) from the 1st process?

Thanks Anton.

junpengl commented 6 years ago

I encountered the same issue with plumbum 1.6.3 and python 2.7.10. I can reproduce that on my local machine with simple code like:

from plumbum import local
local["touch"]("cant/touch")

The output is

Traceback (most recent call last):
  File "test_local.py", line 9, in <module>
    local["touch"]("cant/touch")
  File "/home/junpeng/.pyenv/versions/pipeline-trusted/lib/python2.7/site-packages/plumbum/commands/base.py", line 96, in __call__
    return self.run(args, **kwargs)[1]
  File "/home/junpeng/.pyenv/versions/pipeline-trusted/lib/python2.7/site-packages/plumbum/commands/base.py", line 226, in run
    return p.run()
  File "/home/junpeng/.pyenv/versions/pipeline-trusted/lib/python2.7/site-packages/plumbum/commands/base.py", line 188, in runner
    return run_proc(p, retcode, timeout)
  File "/home/junpeng/.pyenv/versions/pipeline-trusted/lib/python2.7/site-packages/plumbum/commands/processes.py", line 206, in run_proc
    return _check_process(proc, retcode, timeout, stdout, stderr)
  File "/home/junpeng/.pyenv/versions/pipeline-trusted/lib/python2.7/site-packages/plumbum/commands/processes.py", line 23, in _check_process
    proc.verify(retcode, timeout, stdout, stderr)
  File "/home/junpeng/.pyenv/versions/pipeline-trusted/lib/python2.7/site-packages/plumbum/machines/base.py", line 22, in verify
    stdout, stderr)
plumbum.commands.processes.ProcessExecutionError

I believe the root cause is in

         stdout = "\n         | ".join(str(self.stdout).splitlines()) 
         stderr = "\n         | ".join(str(self.stderr).splitlines()) 

The str() will throw another exception if there are utf-8 characters, which happens on my machines. The stderr is touch: cannot touch ‘cant/touch’: No such file or directory (Note the quotes around command are not ascii characters). @henryiii Is that worth to fix this issue? Or should I force my bash to output ascii only characters?

sashkab commented 5 years ago

I've run into similar issue. I have tar | gpg pipe, and when tar unable to read the file, it raises and exception but there is empty stderr... any ideas how to fix this?

erichulser commented 4 years ago

I'd opened a bug before seeing these issues, I posted a suggested fix here: #486