Миграция WEB-приложения Django с версии 2.7 на 3.5 (на практическом примере)


Про консоль управления виртуализацией WebVirtCloud (бывший WebVirtManager) я уже как то рассказывал, но главной его проблемой как я уже сказал является то что он пострен на базе устаревшего Python2 и автор тащит его вперед именно в таком виде. Переписывать он его отказывается мотивируя это тем что все и так работает, но на самом деле там внутри довольно много легаси-мусора. Я его умудился немного переписать под свежую редакцию Django и Python3, но дело еще далеко до завершения хотя пользоваться уже можно.

Миграция WEB-приложений с Python 2.7 на 3

Честно говоря не так сложно все это переписывать, чем бороться с мелкими и крупными багами которые вылезают на ровном месте и требуют глубокой отладки. Одному переписывать такое проект довольно тяжело, поэтому буду рад всем кто захочет помочь в этом нелегком деле.

В процессе работы я описал несколько типовых операций миграции с которыми вы наверняка столкнетесь если решите повторить этот эксперимент.

Ошибка - Exception Value: module 'string' has no attribute 'letters'

Меняем:

def randomPasswd(length=12, alphabet=string.letters + string.digits):
    """Generate a random password"""
    return ''.join([random.choice(alphabet) for i in xrange(length)])

на 

def randomPasswd(length=12, alphabet=string.ascii_letters + string.digits):
    """Generate a random password"""
    return ''.join([random.choice(alphabet) for i in xrange(length)])

Символ L в конце числа

В Python 2.7 L использовался для указания типа Long integer.

Python 3 will never add the L. Not when using repr(), and not when using str(). There would be no point; all integers in Python 3 are long integers.

Можно L убирать.

Ошибка в выражении raise ValueError, "only IPv4 and IPv6 supported"

Конструкция вида:

raise ValueError, "only IPv4 and IPv6 supported"

Превращается в:

raise ValueError ("only IPv4 and IPv6 supported")

Что мне кажется более логичным.

Ошибка - Exception Value: name 'unicode' is not defined

В Python 3, все строки теперь Unicode следовательно преобразования вида:

host = unicode(host)
login = unicode(login)
passwd = unicode(passwd) if passwd is not None else None

Можно свести к виду:

#host = unicode(host)
#login = unicode(login)
passwd = passwd if passwd is not None else None

Просто избавляемся от unicode(value)

Ошибка - Exception Value: module 'string' has no attribute 'lowercase'

Аналогична рассмотренной ранее и требует замены:

string.lowercase

на

string.ascii_lowercase

Ошибка - Exception Value: name 'xrange' is not defined

Дело в том, что xrange была переименована в range в Python3 и соответственно просто меняем:

xrange на range

Список можно продолжать долго, но разумнее наверное просто будет опубликовать наработки относительно работоспособного проекта в GIT где вы сможете все увидеть по каммитам.