HippoMan
HippoMan

Reputation: 2328

python3: Forcing utf-8 for stdout/stderr without externally setting PYTHONIOENCODING?

I'm using python3, and I want my program to utilize utf-8 for stdout and stderr without my having to set the PYTHONIOENCODING environment variable to utf-8 outside of the python program.

In other words, I want the choice of forcing utf-8 output to be contained within the python program itself, no matter what setting of PYTHONIOENCODING or lack thereof might have been specified in the invoker's environment.

The only python3-specific way to accomplish this that I've figured out so far is to start the program as follows:

#!/usr/bin/python3.6                                                                                                            

import os
import sys
if os.environ.get('PYTHONIOENCODING', '').lower() != 'utf-8':
    os.environ['PYTHONIOENCODING'] = 'utf-8'
    sys.exit(os.execl(
        sys.executable, 
        os.path.basename(sys.executable), 
        *sys.argv
    ))

# Remainder of my program ...

Ideally, I'd like to implement this without having to re-exec the python3 interpreter, but I fear that I'm probably out of luck.

Any suggestions? Thank you very much.

ADDENDUM:

Per the comments in the answer, below, I tried the following, but it doesn't print anything ...

#!/usr/bin/python3.6
open(sys.stdout.buffer.fileno(), 'w', encoding='utf8')
open(sys.stderr.buffer.fileno(), 'w', encoding='utf8')
print('Seems to be working')
sys.exit(0)

I also tried utf-8 (with the hyphen), and it doesn't print anything, either.

Upvotes: 1

Views: 777

Answers (3)

methane
methane

Reputation: 479

As of Python 3.7, TextIOWrapper has reconfigure method for you:

sys.stdin.reconfigure(encoding="utf-8")
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")

Upvotes: 1

HippoMan
HippoMan

Reputation: 2328

And now I understand better what lenz suggested, and I figured out the answer:

#!/usr/bin/python3.6
import os
import sys
sys.stdout = os.fdopen(sys.stdout.buffer.fileno(), 'w', encoding='utf8')
sys.stderr = os.fdopen(sys.stderr.buffer.fileno(), 'w', encoding='utf8')

Upvotes: 0

Michael Dyck
Michael Dyck

Reputation: 2458

Some people suggest

sys.stdout = codecs.getwriter("UTF-8")(sys.stdout)

Others say that may break some libraries.

Upvotes: 1

Related Questions