SyntaxError с маринованными целыми числами при переносе приложения с использованием django-q на Python 3 - PullRequest
0 голосов
/ 07 мая 2019

Этот вопрос характерен для использования django-q с Django ORM в качестве бэкэнда очереди, поскольку основной причиной, по-видимому, является использование pickle в их модели Django. (Тем не менее, pickle может использоваться для других бэкэндов в django-q.)

Проблема

При портировании существующего приложения с использованием django-q на Python 3, я заметил, что в строках регистрации появляются жалобы на следующее:

2019-05-06 09:52:12,859 ERROR django-q: invalid syntax (<unknown>, line 1) [in /usr/local/lib/python3.6/dist-packages/django_q/cluster.py:558, 140417530787648 (MainThread), 27943 (Process-1)]
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/django_q/cluster.py", line 506, in scheduler
    args = ast.literal_eval(s.args)
  File "/usr/lib/python3.6/ast.py", line 48, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/lib/python3.6/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    (320L,)
        ^
SyntaxError: invalid syntax

(Обратите внимание, что если вы используете django-q, вы фактически не получите трассировку: я отредактировал строку регистрации в django_q/cluster.py до logger.exception вместо logger.error.)

Эта ошибка имеет смысл, потому что django-q хранил длинные целые числа (в данном случае идентификаторы модели) с завершающим L (pickle снова наносит удар). Хотя в Python 2 работает следующее, в Python 3 не удается выполнить синтаксический анализ:

>>> import ast
>>> ast.literal_eval('(320L,)')
  File "<unknown>", line 1
    (320L,)
        ^
SyntaxError: invalid syntax

Возможные решения

Я думаю, что мои варианты:

  1. Написать миграцию для преобразования длинных целых
    • Используйте регулярные выражения для преобразования целых чисел
    • Используйте 2to3 для преобразования данных (которые будут обрабатывать другие типы данных в дополнение к целым числам)
  2. Патч django-q для отлова SyntaxError и преобразования данных
    • Используйте либо регулярное выражение или 2to3 для преобразования данных

В библиотеке lib2to3 есть предупреждения о нестабильном API, но что-то вроде этого работает для меня (на Python 3.6):

from lib2to3.refactor import RefactoringTool, get_fixers_from_package

refactoring_tool = RefactoringTool(fixer_names=get_fixers_from_package('lib2to3.fixes'))

def convert_data_2to3(pickled_data):
    # Add new-line: refactoring tool requires lines of code.
    data = pickled_data + '\n'
    node = refactoring_tool.refactor_string(data, 'convert_data_2to3')
    return str(node).rstrip()  # Strip the newline added earlier

Вопрос

Ни один из вышеперечисленных вариантов не кажется отличным. Любые другие варианты?

...