- Оригинальный адрес:Moving a large and old codebase to Python3
- Оригинальный автор:Anders Hovmöller
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:Starrier
- Корректор:LynnShaw,steinliber
Перенос старого большого проекта на Python 3
Полтора года назад мы решили использовать Python 3. Мы говорили об этом в течение долгого времени, теперь пришло время использовать это! Теперь, когда процесс завершен, мы перенесли окончательное развертывание производства на Python 3.
- Вся кодовая база составляет около 240 тысяч строк, не считая пустых строк и комментариев.
- Это веб-система пакетных задач. И есть только одна рабочая среда, среда развертывания.
- Кодовой базе около 15 лет.
- Хотя это приложение Django, части кода были написаны до того, как Django был выпущен.
Немного базовой статистики об изменениях в Python 3, основанной на грубой фильтрации истории коммитов git:
- 275 коммитов
- Добавлено 4080 строк кода
- 3432 удалить строки кода
Я нашел 109 задач jira, связанных с этим проектом.
Py2 → шесть → py3
Наша философия всегда была py2 →py2/py3 →py3, потому что мы просто не можем вносить большие изменения в реальное производство, и эта интуиция удивительным образом оказалась верной. это означаетот 2 до 3Это невозможно, я думаю, что это довольно распространено. Мы пытались использовать от 2 до 3 для обнаружения проблем совместимости с Python 3, но вскоре это оказалось невозможным. По сути, такое изменение означает, что код в Python 2 будет сломан. Такое изменение невозможно.
Вывод - использоватьsix, которая представляет собой библиотеку, упрощающую создание кодовой базы, которая работает как в Python 2, так и в Python 3.
Первое, что нужно сделать, это обновить предыдущие зависимости. Эту работу необходимо начать сейчас, потому что позже будет обновлено больше контента.
модернизация
Python-modernizeэто инструмент, который мы выбрали для миграции. Это инструмент, который автоматически преобразует кодовую базу Py 2 в кодовую базу, совместимую с шестью. Сначала мы вводим тест как часть CI, чтобы проверить, готов ли новый код, основанный на модернизации, для py3. Самый большой эффект от этого заключается в том, чтобы те, кто все еще использует синтаксис Py 2, знали о новом способе ведения дел, но, очевидно, это мало что дает для преобразования существующих 240 тысяч строк кода в шесть. У всех нас есть дурная привычка использовать старый синтаксис, и это, возможно, педагогический успех, хотя он не имеет значения для количества строк кода, он также используется нами для экспериментальной ветки:
экспериментальная ветвь
Я создал новую ветку под названием «Python 3» и сделал следующее:
- Запустите «python-modernize -n -w» для всей кодовой базы. Он изменяет код там, где это необходимо. Я часто начинаю исправлять код после выполнения этого шага, не делая первого коммита. Этот неверный шаг всегда вызывал у меня сожаление и заставлял не раз начинать все сначала. Даже если этот этап пойдет не так, лучше сначала зафиксировать его. Поэтому важно разделять то, что делают машины и люди.
- Импортируйте все зависимости для тел функций в py3, которые мы еще не исправили.
Идея здесь состоит в том, чтобы «забежать вперед», т.е. посмотреть, с какими проблемами мы столкнемся, если не будем использовать устаревшие зависимости. Эта ветвь позволяет мне очень быстро запустить приложение в состоянии суперпаузы и, по крайней мере, запустить некоторые модульные тесты. Эта ветка совсем другая, но я все же нашел способ применить ее к соответствующим сценариям. Я использую отличный GitUp для разделения, объединения и фиксации. Когда коммит выглядит хорошо, я выбираю его в новую ветку и отправляю на проверку кода.
Никто не может работать с этой веткой, потому что она постоянно перебазируется, принудительно нажимается, злоупотребляется, но она продвигает проект вперед, не дожидаясь обновления всех зависимостей. Очень рекомендую использовать этот метод!
статический анализ
Мы добавили хуки перед фиксацией, так что если вы отредактируете файл, вам будет предложено модернизировать все обновления Python 3.
quote_plusРучной статический анализ . Существуют небольшие различия в обработке quote_plus и six . Наконец, мы создали собственную оболочку, которую код по умолчанию принудительно использует вместо той, что есть в стандартной библиотеке, или той, что есть в six . Мы также статически проверяем байты, которые вы никогда не отправляете в quote_plus.
Мы исправили все проблемы с Python 3 в каждом приложении diango и усилили это с помощью белого списка в среде CI, поэтому вы не сможете сломать приложение, которое когда-либо было исправлено.
полагаться
Для нас самой сложной частью было разрешение зависимостей. У нас было много зависимостей, поэтому это заняло много времени, две из которых были сложными:
- splunk-lib Мы зависим от splunk, но они до сих пор игнорируют всеЗлой клиент просит о совместимости с py3 для клиента. один из нашей командыНаконец-то сам разобрался. Splunk справился с этим очень плохо, он даже заблокировал этот вопрос в этом разделе комментариев! Это просто неприемлемо.
- Cassandra Весь наш продукт использует эту базу данных, но мы используем старый драйвер с предыдущими модулями API. Для нас это была огромная часть процесса миграции py3, поэтому нам пришлось переписывать весь этот код по частям.
контрольная работа
Наш охват тестами кода составляет около 65%, включая: модуль, интеграцию и слияние пользовательского интерфейса. Мы написали больше тестов, но общее количество не сильно изменилось. Неудивительно, если учесть, что увеличение охвата с 65% до 66% потребует написания почти 2000 строк кода тестов.
Приходится пропускать тесты, требующие Cassandra, и заодно исправлять эту зависимость. Я придумал забавный маленький лайфхак, чтобы заставить его работать,и писали статьи об этом.
изменения кода
Примечание об изменениях кода, не упомянутых в документации по переносу py2 на six (возможно, мы пропустили):
StringIO
Мы часто используем StringIO в нашем коде. Первая реакция — использовать шесть. Но для StringIO это оказывается неверным почти во всех случаях (но не во всех!). По сути, мы должны очень тщательно обдумывать каждое место, где мы используем StringIO, и пытаться выяснить, следует ли нам вместо этого использовать io.StringIO, io.BytesIO или six.StringIO. Ошибки здесь обычно подготовлены для того, что выглядит как совместимый с py3 код, который отлично работает в py2, но на самом деле не работает в py3.
отfutureимпортировать unicode_literals в
Это смешанная сумка. Вы можете найти ошибки, добавив его во многие файлы, но иногда ошибки появляются в py2. Это также может вызвать беспокойство, когда журнал внезапно оказывается в странных местах, например, пишет «u» перед строкой. В общем, это явно не то, что я ожидал.
str/bytes/unicode
Это в значительной степени то, что вы ожидаете. Я удивлен, что str требуется в py2 и py3 . Если в будущем вы будете импортировать с использованием unicode_literals, то некоторые строки необходимо будет импортировать из'foo'превратиться вstr('foo').
six.moves
Реализация six.moves — довольно странный хак, поэтому он не ведет себя как обычный модуль Python, за который притворяется. Я также не согласен с тем, что они не включают в six.movesmockс Выбор. Нам пришлось использовать их API, чтобы добавить его самостоятельно, но нам было трудно начать работу, и нам потребовалось добавитьfrom mock import patchизменить наfrom six.moves import mockЭто также означаетpatchтеперь становитсяmock.patch.
Парсинг CSV отличается
Если вы используете модуль csv, вам нужно знать о csv342. Мне кажется, что это должна быть часть шесть. В противном случае это означает, что вы не поняли, что есть проблема. Мы не используем csv342 во многих местах, поэтому то, что вам нужно сделать здесь, может отличаться.
приказ об освобождении
Сначала протестируем:
- Модульное тестирование в CI
- Интеграция и тестирование пользовательского интерфейса в CI (кроме Cassandra)
- Проведите тесты Cassandra в CI (это позже, чем предыдущие шаги!)
Далее сам продукт. Мы создаем пакетную машину с возможностью одновременного переключения на py3 и, что особенно важно, обратного переключения. Это становится важным, когда на py3 происходят разрывы. Это очень удобно для нас, потому что мы можем повторно ставить в очередь прерванные задачи, но мы не можем прерывать слишком много или какие-либо действительно важные задачи. Мы используем Sentry для сбора журналов сбоев, поэтому легко увидеть все проблемы, которые у нас были при переходе на py3, и когда мы исправим все проблемы, нам нужно снова мигрировать на py3, пока не возникнут какие-то проблемы, и так далее.
У нас есть следующая среда:
- Devtest: используется разработчиками внутри компании, поэтому в большинстве случаев это просто проверка миграции базы данных. Эта среда очень проста в использовании, поэтому здесь не часто случаются ошибки.
- IAT (внутреннее приемочное тестирование): используется для проверки изменений и выполнения регрессионного тестирования, прежде чем мы отправим изменения в производство.
- UAT (приемочное тестирование пользователей): тестовая среда, доступная для клиентов. Используется для изменений, которые требуют подготовки клиентских систем, или для клиентов, чтобы просмотреть изменения перед их вводом в действие. Эта среда не переносится за несколько дней до переноса базы данных.
- Производственная среда
Мы выпускаем Python 3 для этих сред в следующем порядке:
- Среда для разработчиков
- Краткосрочная среда IAT
- Долгосрочная среда IAT
- Машина для мелкосерийного производства
- Машина серийного производства, используемая во время работы
- Производство SFTP
- серийные машины, на которые приходится половина производства
- производственная партия
- Рабочий веб-сайт (после длительного ручного тестирования тестовой среды)
- Производственная загрузочная машина. Это особое подмножество пакетной обработки. Он завершает большую часть процессора и памяти нашего продукта.
Машина загрузки выявила конфигурации клиентских данных, которые были несовместимы с Python 3, поэтому нам пришлось реализовать предупреждения для этих случаев в Python 2 и убедиться, что они исправлены, прежде чем снова включить Python 3. Это заняло несколько дней, и поскольку мы получали данные о клиентах каждый день, каждый раз появлялось предупреждение, из-за чего нам приходилось ждать еще день.
Сюрприз в производстве
-
'ß'.upper()в py2 есть'ß'Но в py3 это'SS'. Когда последняя часть продукта была перенесена на py3, это привело к сбою продукта! - Сравнение и сортировка объектов разных типов в py2 работает, но это скрывает множество багов. Мы получили несколько неприятных сюрпризов, потому что это поведение каким-то неочевидным образом просочилось из стека, особенно в некоторых отсортированных списках.
Noneкогда. В целом, это победа, потому что мы нашли довольно много ошибок.NoneМожет показаться неожиданным, что py2 стоит первым в списке (можно ожидать, что он будет отсортирован близко к нулю!), теперь нам просто нужно с ними разобраться. -
'{}'.format(b'asd')В питоне 2 да'asd', но в Python 3 есть"b'asd'". В Python 3 почти любое другое поведение здесь было бы лучше: вывод в шестнадцатеричном виде (результаты отличаются значительно больше), старое поведение (предыдущий запуск кода) или выдача исключения (лучшее поведение!). -
int('1_0')В py 3 результат равен 10, но не работает в py2. Это беспокоило нас еще до перехода на py3. Потому что это несоответствие привело к тому, что другая команда, которая использовала py3 до нас, отправила нам действительные значения, которые мы считали недействительными, но они считали их действительными. Я лично считаю это решение неправильным: очень строгий синтаксический анализ — лучший выбор по умолчанию, и я боюсь, что это будет продолжать преследовать нас в скрытых формах в течение многих лет.
в заключении
В конце концов, мы чувствуем, что у нас действительно нет выбора в этом вопросе: поддержка Python 2 в какой-то момент прекратится, а наши зависимости ограничены py3, в первую очередь Django. Тем не менее, мы все равно хотим сделать это преобразование, так как мы часто сталкиваемся с проблемами байтов/Unicode, а Python 3 просто исправляет множество мелких неприятностей в Python 2. Во время этой миграции мы обнаружили некоторые фактические ошибки/неправильные конфигурации в рабочей среде. Мы также ожидаем, что f-строки и упорядоченные словари будут доступны повсюду.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллекти другие поля, если вы хотите видеть больше качественных переводов, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.