Skip to content
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

Fails to color Windows console #1832

Closed
mrx23dot opened this issue May 3, 2020 · 7 comments · Fixed by #2012
Closed

Fails to color Windows console #1832

mrx23dot opened this issue May 3, 2020 · 7 comments · Fixed by #2012
Labels
Milestone

Comments

@mrx23dot
Copy link

mrx23dot commented May 3, 2020

On windows the new Flask prints weird characters on console, instead of coloring the line as on linux. eg: "←[37m

I would rather go black/white (like in previous version) if coloring doesnt work.

2020-05-03 14:05:47,398 - INFO - 127.0.0.1 - - [03/May/2020 14:05:47] "←[37mGET /result HTTP/1.1←[0m" 200 -
2020-05-03 14:06:42,922 - INFO - 127.0.0.1 - - [03/May/2020 14:06:42] "←[37mGET /result HTTP/1.1←[0m" 200 -
2020-05-03 14:07:24,007 - INFO - 127.0.0.1 - - [03/May/2020 14:07:24] "←[37mGET /result HTTP/1.1←[0m" 200 -
2020-05-03 14:07:24,210 - INFO - 127.0.0.1 - - [03/May/2020 14:07:24] "←[37mGET /static/images/favicon.ico HTT
2020-05-03 14:08:19,539 - INFO - 127.0.0.1 - - [03/May/2020 14:08:19] "←[37mGET /result HTTP/1.1←[0m" 200 -
2020-05-03 14:09:15,065 - INFO - 127.0.0.1 - - [03/May/2020 14:09:15] "←[37mGET /result HTTP/1.1←[0m" 200 -
2020-05-03 14:10:10,579 - INFO - 127.0.0.1 - - [03/May/2020 14:10:10] "←[37mGET /result HTTP/1.1←[0m" 200 -

Env:
Flask==1.1.2
Win7 x64
Python 3.6.7 x64
Werkzeug==1.0.1

@H1tman1978
Copy link

I was unable to duplicate.

Command Prompt view:
image

Pycharm Terminal:
image

PyCharm Run:
image

I'm running Windows 10 x64, Python 3.7.4, flask 1.1.2, Werkzeug 1.0.1

@davidism
Copy link
Member

davidism commented May 4, 2020

I'm not really sure how to explain this. If anything, is an issue with Click, but Click isn't supposed to emit color info on Windows if colorama isn't installed. I have seen more reports of this since switching to Click, but it's not consistent, as shown in the previous screenshots.

@mrx23dot
Copy link
Author

mrx23dot commented May 4, 2020

Tested on Win7 and Win10 same issue, although I see coloring working, just not for REST calls:
2020-05-04_215343

I have these installed:
click==7.1.1
colorama==0.4.3
coloredlogs==14.0

These all work with coloring:
from colorama import Fore, Back, Style
print(Fore.RED + 'some red text')
print('\033[31m' + 'some red text')

import click
click.echo('\033[31m' + 'some red text')

from Flask:
"←[37mGET " <- this might be escaped invalidly in the code (needs double back slashes?), it worked for me with single

@jcorvino
Copy link

I was able to correct the issue by adding the following code to my flask app

import os
import sys

if sys.platform.lower() == "win32": 
    os.system('color')

See https://stackoverflow.com/questions/287871/how-to-print-colored-text-in-python for details.

It seems that the double brackets are being filtered in the logs as @mrx23dot suggested.

@jcorvino
Copy link

jcorvino commented Oct 3, 2020

I spent some more time investigating this issue. The color addition comes from click.style. Here's the relevant code from serving.WSGIRequestHandler:

def log_request(self, code="-", size="-") -> None:
        try:
            path = uri_to_iri(self.path)
            msg = f"{self.command} {path} {self.request_version}"
        except AttributeError:
            # path isn't set if the requestline was bad
            msg = self.requestline

        code = str(code)

        if click:
            color = click.style

            if code[0] == "1":  # 1xx - Informational
                msg = color(msg, bold=True)
            elif code[0] == "2":  # 2xx - Success
                msg = color(msg, fg="white")
            elif code == "304":  # 304 - Resource Not Modified
                msg = color(msg, fg="cyan")
            elif code[0] == "3":  # 3xx - Redirection
                msg = color(msg, fg="green")
            elif code == "404":  # 404 - Resource Not Found
                msg = color(msg, fg="yellow")
            elif code[0] == "4":  # 4xx - Client Error
                msg = color(msg, fg="red", bold=True)
            else:  # 5xx, or any other response
                msg = color(msg, fg="magenta", bold=True)

        self.log("info", '"%s" %s %s', msg, code, size)

You can see that the click.style function is simply wrapping the initial message in ANSI style codes. For Linux and OS X, ANSI codes are supported by default, so those users won't notice this issue. However, on Windows, the terminal does not support this by default. If using Windows 10, a simple workaround is to use the following command to enable ANSI styling:

import sys
import os

if sys.platform.lower() == 'win32':
    os.system('color')

This will address most users with the issue, but might not fix some edge cases (e.g. small-footprint or embedded unix distros). The os.system('color') (or really any os.system call) can be put almost anywhere in the code base. As long as it is called before the output is printed, the output will show up properly colored. This is probably why users of PyCharm don't notice the bug. The PyCharm python terminal likely makes an os.system call to handle colored text output.

So the way I see it there are 2 questions:

  1. Should werkzeug fix this minor issue or leave the burden on Windows 10 users to call os.system?
  2. If we fix this in werkzeug, where should we add the os.system call? It only needs to be called once, so perhaps it could be added to WSGIRequestHandler.__init__? There are probably better options, but that's all I can think of right now.

@Silickr
Copy link

Silickr commented Dec 18, 2020

I was able to correct the issue by adding the following code to my flask app

import os
import sys

if sys.platform.lower() == "win32": 
    os.system('color')

See https://stackoverflow.com/questions/287871/how-to-print-colored-text-in-python for details.

It seems that the double brackets are being filtered in the logs as @mrx23dot suggested.

Thanks. add the code in config.py , it's works for me. 😀

@davidism davidism added this to the 2.0.0 milestone Jan 16, 2021
@davidism
Copy link
Member

I looked into the os.system hack, and it appears to be an unintended side effect of how cpython interacts with the Windows API, leaving some global state changed after the process ends. I don't want to rely on that.

When I switched to Click for styling, I thought it would handle not setting styles on Windows, but it turns out click.style isn't concerned with that (and can't really be), it's click.echo that handles stripping the ANSI codes if needed based on the output stream. Also, Click doesn't call colorama.init() because it wants to avoid changing global state, instead click.echo wraps the stream with colorama locally.

Since the logging module uses its own output system (StreamHandler in this case), colorama would have to be enabled globally, or the handler could be replaced with a custom one that wraps the stream or strips the codes. The problem with that is that if users configure their own logging (such as adding a root handler), they suddenly have to deal with the same issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants