Skip to content

Suggestion: write messages to stdout instead of stderr #1051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gvanrossum opened this issue Dec 5, 2015 · 9 comments
Closed

Suggestion: write messages to stdout instead of stderr #1051

gvanrossum opened this issue Dec 5, 2015 · 9 comments

Comments

@gvanrossum
Copy link
Member

I often want to grep mypy's output for certain messages (or to strip certain messages) and this is a little tricky because the messages are written to stderr. So I have to do e.g.

mypy file.py 2>&1 | grep -v note

instead of

mypy file.py | grep -v note

I think the only things that should be written to stderr are command line syntax errors (where it refuses to run) or fatal errors like tracebacks. Syntax errors in the modules to be analyzed should probably go to stdout (though since these abort processing it might be okay to send these to stderr).

Also -h output should go to stdout IMO (this is how argparse does things -- it would also be nice to rewrite the argument parsing using argparse).

@refi64
Copy link
Contributor

refi64 commented Dec 5, 2015

I'm really -1 on this. Literally every static type checker or compiler I know uses stderr for cough errors.

@gvanrossum
Copy link
Member Author

gvanrossum commented Dec 5, 2015 via email

@JukkaL
Copy link
Collaborator

JukkaL commented Dec 5, 2015

I'm okay with changing this. If mypy would behave like pylint, flake8 in this respect it probably wouldn't be surprising for most users. But I guess we could ask more people about their opinion if this is a controversial issue -- maybe there are some valid reasons for keeping the current behavior.

@darjus
Copy link
Contributor

darjus commented Dec 6, 2015

I'm with Guido on this one. Apart from Python linters writing to stdout - I usually write things that are part of normal program operation to stdout (and in this context most of mypy's output is part of normal operation), and truly erroneous things like stack traces and parse errors to sderr. This way i can grep for specific outputs with ease, and most importantly, if something horrible happens, it would not disappear if grep does not include it.

Here's how i would imagine it working:

# mypy detected type error
STDOUT: outs/int_plus_str.py: note: In function "str_plus_int":
STDOUT: outs/int_plus_str.py:4: error: Incompatible return value type: expected builtins.str, got builtins.int

# mypy could not parse the file
STDERR?: outs/parse_error.py: note: At top level:
STDERR?: outs/parse_error.py:1: error: Parse error before string literal

# mypy crashed
STDERR: Traceback (most recent call last):
STDERR:   File "bin/mypy", line 6, in <module>
STDERR:     main(__file__)
STDERR:   File "lib/python3.4/site-packages/mypy/main.py", line 50, in main
STDERR:     type_check_only(sources, bin_dir, options)
STDERR:   File "lib/python3.4/site-packages/mypy/main.py", line 93, in type_check_only
STDERR:     python_path=options.python_path)
STDERR:   File "lib/python3.4/site-packages/mypy/build.py", line 179, in build
STDERR:     raise RuntimeError("Darjus crashed mypy")
STDERR: RuntimeError: Darjus crashed mypy

@gvanrossum
Copy link
Member Author

Yeah, that would be ideal. Unfortunately the way the parser errors are
generated makes it hard to send those to a different stream -- the code is
in a number of different places and they're not all fatal. We should make
sure that at least one message is written to stderr when the program's exit
status is nonzero though.

On Sun, Dec 6, 2015 at 12:58 AM, Darjus Loktevic [email protected]
wrote:

I'm with Guido on this one. Apart from Python linters writing to stdout -
I usually write things that are part of normal program operation to stdout
(and in this context most of mypy's output is part of normal operation),
and truly erroneous things like stack traces and parse errors to sderr.
This way i can grep for specific outputs with ease, and most importantly,
if something horrible happens, it would not disappear if grep does not
include it.

Here's how i would imagine it working:

mypy detected type error

STDOUT: outs/int_plus_str.py: note: In function "str_plus_int":
STDOUT: outs/int_plus_str.py:4: error: Incompatible return value type: expected builtins.str, got builtins.int

mypy could not parse the file

STDERR?: outs/parse_error.py: note: At top level:
STDERR?: outs/parse_error.py:1: error: Parse error before string literal

mypy crashed

STDERR: Traceback (most recent call last):
STDERR: File "bin/mypy", line 6, in
STDERR: main(file)
STDERR: File "lib/python3.4/site-packages/mypy/main.py", line 50, in main
STDERR: type_check_only(sources, bin_dir, options)
STDERR: File "lib/python3.4/site-packages/mypy/main.py", line 93, in type_check_only
STDERR: python_path=options.python_path)
STDERR: File "lib/python3.4/site-packages/mypy/build.py", line 179, in build
STDERR: raise RuntimeError("Darjus crashed mypy")
STDERR: RuntimeError: Darjus crashed mypy


Reply to this email directly or view it on GitHub
#1051 (comment).

--Guido van Rossum (python.org/~guido)

@darjus
Copy link
Contributor

darjus commented Dec 7, 2015

I'm not too familiar with mypy codebase yet but could we use standard python logging facilities?

I remember seeing an issue where Jukka discusses warning messages and that currently everything's an error in mypy and it would be useful to support both. By using logging and handlers we could support this quite easily and could give extra flexibility on what to print where/when.

log = logging.getLogger(__name__)  # or maybe different name/namespace
log.debug("Various debug messages that would be printed to STDOUT if --debug or -vv was passed in with line numbers and additional formatting information useful for debugging")
log.info("Various informational messages (for example: checking file spam/eggs.py) that would be enabled with --verbose")
log.warn("Would print STDOUT warning messages relating to various warnings in code being checked")
log.error("Woud print STDOUT errors relating to errors in code being checked")
log.critical("Would print STDERR various critical things we've touched up on above")

@gvanrossum
Copy link
Member Author

IMO the logging module isn't really meant for this use case. We want the
output to be compatible with grep -n so it can be parsed by various filters
(e.g. Emacs compilation buffers).

On Sun, Dec 6, 2015 at 6:11 PM, Darjus Loktevic [email protected]
wrote:

I'm not too familiar with mypy codebase yet but could we use standard
python logging facilities?

I remember seeing an issue where Jukka discusses warning messages and that
currently everything's an error in mypy and it would be useful to support
both. By using logging and handlers we could support this quite easily and
could give extra flexibility on what to print where/when.

log = logging.getLogger(name) # or maybe different name/namespace
log.debug("Various debug messages that would be printed to STDOUT if --debug or -vv was passed in with line numbers and additional formatting information useful for debugging")log.info("Various informational messages (for example: checking file spam/eggs.py) that would be enabled with --verbose")
log.warn("Would print STDOUT warning messages relating to various warnings in code being checked")
log.error("Woud print STDOUT errors relating to errors in code being checked")
log.critical("Would print STDERR various critical things we've touched up on above")


Reply to this email directly or view it on GitHub
#1051 (comment).

--Guido van Rossum (python.org/~guido)

@darjus
Copy link
Contributor

darjus commented Dec 7, 2015

You're right, with different possible reporting output types it would be preferable to have pluggable outputs.
Similar to pylint or coverage.py reporter maybe?
I prefer clang error outputs to gcc and it would be awesome if we could adapt coverage.py annotate reporter for similar purpose.
Though i see mypy already has a report.py module, so maybe a better approach would be to refactor errors.py and messages.py to a default stdout reporter.

Anyway, sorry for the detour :)

https://bitbucket.org/logilab/pylint/src/4e5a1be18df2/pylint/reporters/?at=default
https://github.com/nedbat/coveragepy/blob/master/coverage/report.py
https://github.com/nedbat/coveragepy/blob/master/coverage/annotate.py
http://clang.llvm.org/diagnostics.html

@JukkaL JukkaL closed this as completed in 6ba94d3 Dec 28, 2015
@gvanrossum
Copy link
Member Author

Looks like this was broken again by a978ec0. I'll fix it by adding a flag to CompileError which will be set only when it's raised from Errors.raise_error().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants