Миграция Python 2–3 - UnicodeEncodeError: кодек «ascii» не может кодировать символ ...: порядковый номер не находится в диапазоне - PullRequest
0 голосов
/ 03 октября 2019

В настоящее время я переносю веб-приложение, написанное на Flask (Python 2.7), на Python 3. До сих пор мне удалось заставить все работать, но есть один небольшой косметический бит, который меня абсолютно смущает, и я не могу исправитьЭто.

Это файл, который выполняет статический анализ кода - run_pylint.py. Я собираюсь немного сократить файл с важными вещами.

RESULT_EXPRESSION = re.compile(r'Your code has been rated at (\d*\.*\d*)/10')

VALIDATION_PERFECT = "✓ Pylint validation SUCCESSFUL! Perfect score!"
# and a couple of other options...

class PyLintOutput:
    """
    Pylint report storage and retrieval
    """
    def __init__(self):
        """Initialize the storage"""
        self.content = []
        self.rate = None

    ... # skipping several unimportant methods

def get_rate(self):
    """
    After having been fed with PyLint output (via read()),
    determine the rate given to the module by PyLint.
    :return: A float between 0 (worst) to 10 (no issues detected).
    """
    if self.rate is not None:
        return self.rate

    for line in reversed(self.read()):
        result = re.search(RESULT_EXPRESSION, line)
        if result is None:
            continue

        self.rate = float(result.group(1))
        return self.rate

    return 0

    def __str__(self):
        """
        Get the full Pylint output as a string.
        """
        return "".join(self.content)

if __name__ == '__main__':
    # instance of the class
    OUT = PyLintOutput()

    # run PyLint static code analysis
    Run([MODULE_NAME], reporter=TextReporter(OUT), do_exit=False)

    if OUT.get_rate() < THRESHOLD:
        # if under threshold it prints a message to fix the bugs..
    elif OUT.get_rate() == THRESHOLD:
        # imperfect validation
    else:
        # perfect score
        print(VALIDATION_PERFECT)

Надеюсь, идея ясна. Итак, скажем, счет действительно идеальный, поэтому он переходит к условию else, которое должно напечатать сообщение:

✓ Pylint validation SUCCESSFUL! Perfect score!

Это происходит в моей консоли (я использую PyCharm). Однако для развертывания этого веб-приложения я использую Docker и Jenkins. Краткое объяснение: Docker-контейнер, работающий с CentOS с Python 3.6, который создает веб-приложение. Одним из шагов при создании веб-приложения является статический анализ кода. Если это не удается, развертывание не выполняется. Все это развертывание происходит за одно задание Дженкинса. Это журнал консоли, когда он достигает того же шага, о котором я упоминал выше:

[91mTraceback (most recent call last):
  File "run_pylint.py", line 123, in <module>
    print(VALIDATION_PERFECT)
UnicodeEncodeError: 'ascii' codec can't encode character '\u2713' in position 0: ordinal not in range(128)

Я не уверен, почему он не отображается в моей консоли таким же образом. Я исправил подобные проблемы с другими частями кода во время миграции. Естественно, я пробовал кучу разных вещей, в том числе:

1)

    VALIDATION_PERFECT = u"✓ Pylint validation SUCCESSFUL! Perfect score!"
...
else:
     print(VALIDATION_PERFECT.encode("utf8))

Now, the tests pass, but the string is shown like this (in a bytes format):
 b'\xe2\x9c\x93 Pylint validation SUCCESSFUL! Perfect score!'

Я попытался расшифровать это, чтобы оно могло стать обычной строкой Python 3, но нет, та же ошибкакак указано выше.

2) Я наткнулся на функцию в переполнении стека, которую я использовал, однако она выдала мне ту же ошибку:

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

3) Я пробовал разные комбинации кодирования / декодированияв "utf8", но безуспешно. Я знаю, что юникод теперь поддерживается в обычной строке в Python 3, и все трюки, которые я пробовал, работают в моей консоли, когда я локально выполняю этот скрипт. Однако проблема сохраняется в моей работе в Дженкинсе.

Кто-нибудь может дать мне какие-нибудь советы?

1 Ответ

1 голос
/ 03 октября 2019

Украденный из этого ответа, вам необходимо установить переменную среды PYTHONENCODING на вашем сервере Jenkins. По-видимому, это можно сделать либо в консоли управления Jenkins, либо перед вызовом сценария проверки Python вы можете выполнить это в оболочке:

export PYTHONIOENCODING=UTF-8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...