Enviroment dependent Python UnicodeEncodeError

Printing none-ASCII characters (╚☻═♜) to terminal with python fails in some environments and in some not. Note that printing non-ASCII characters works in the host python (both 2 and 3) at least on .

The snap is built in an ubuntu 16.04 lxc container.

Minimal example bellow.

Error

In lxc containers running ubuntu 18.04 and 16.04 it works. But in openSUSE TW and Ubuntu 18.04 both running on bare metal I get the following error.

Traceback (most recent call last):
  File "/snap/test/x1/bin/script", line 11, in <module>
    load_entry_point('test==0.1', 'console_scripts', 'script')()
  File "/snap/test/x1/bin/script.py", line 2, in main
    print("\u255a\u263b\u2550\u265c")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

Attempt at a solution

StackOverflow answer

By reading this answer at StackOverflow https://stackoverflow.com/questions/20923663/unicodeencodeerror-ascii-codec-cant-encode-character-in-position-0-ordinal

When Python prints and output, it automatically encodes it to the target medium. If it is a file, UTF-8 will be used as default and everyone will be happy, but if it is a terminal, Python will figure out the encoding the terminal is using and will try to encode the output using that one.
This means that if your terminal is using ascii as encoding, Python is trying to encode scissor char to ascii. Of course, ascii doesn’t support it so you get Unicode decode error.
This is why you always have to explicitly encode your output. Explicit is better than implicit remember? To fix your code you may do:

import sys
sys.stdout.buffer.write(chr(9986).encode('utf8'))

I attempted:

print("╚☻═♜".encode('utf8'))

This solved the above error message now the output on all platforms is:

b'\xe2\x95\x9a\xe2\x98\xbb\xe2\x95\x90\xe2\x99\x9c'

Which does not really solve my problem even though it somewhat of an improvement.

Minimal example

script.py

def main():
  print("╚☻═♜")

if __name__ == '__main__':
  main()

setup.py

from setuptools import setup, Extension

setup(name='test',
      version='0.1',
      entry_points={
        'console_scripts': [
            'script = script:main',
        ],},
      scripts=['script.py'],
)

snapcraft.yml

name: test
version: 1
summary: test. 
description: test.
confinement: devmode 
parts:
  test:
    plugin: python
    python-version: python3
    source: .

apps:
  script:
    command: bin/script

I eventually found the key to a solution in the discussion in this bug report where someone had more or less the exact same problem. https://bugs.launchpad.net/ubuntu/+source/snapd/+bug/1576411

this is due to the fact that snappy does not ship any locale data except C and C.UTF-8 … nor any fonts or keymaps … given that we fully focus on embedded and IoT with the rootfs

Some commented they used a workedaround, manually setting environment variables for the locale.

From the snapcraft yaml reference :

apps <app-name> environment

A set of key-value pairs specifying the contents of environment variables.
Type: dict
Key is the environment variable name; Value is the contents of the environment variable.
Example: LANG: C.UTF-8

Solution

Noting that the example very much looked lite what i was searching for i tested it.

apps:
  script::
    command: bin/scripts
    environment:
      LANG: C.UTF-8

And it worked!

Note

Showing the power of a good problem formulation, writing the question got me in the right direction of solving the issue.