#python #python-3.x
#python #python-3.x
Вопрос:
Поскольку Django пока не поддерживает Python 3.x, я использую Python 2.7. Однако я хотел бы продолжить и начать знакомство с новым синтаксисом Python 3.x настолько, насколько это возможно. Что подводит меня к вопросу:
- Каков наилучший способ написания кода на Python 2.7, который будет максимально совместим с Python 3.x?
Я знаю, что запуск python -3
приведет
Предупреждаю о несовместимости Python 3.x, которую 2to3 не может тривиально исправить.
Тем не менее, я заинтересован в том, чтобы привыкнуть к синтаксису Python 3.x, все еще используя Python 2.7.
Например, кажется, что я должен использовать следующий импорт в свой код:
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import
Вышеупомянутые четыре __future__ import
инструкции требуются начиная с Python 3.0, но не требуются в 2.7, как описано в документации Python 2.7.3 27.11. Определения будущих инструкций
Что еще?
Комментарии:
1. Одним из недостатков этого подхода является то, что если ваша программа имеет зависимости от пакетов, несовместимых с какой-либо утилитой __future __, ваша программа завершится сбоем, и у вас не будет особого контроля. Например, вы используете один из простых пакетов pypi, и в нем есть «print something». В любом случае, спасибо, это хороший вопрос.
2. @Shekhar: эффект
__future__
локализован в модуле, который его импортирует. С инструкцией print проблем нет;from __future__ import print_function
функцию могут использовать только модули, которые находятсяprint()
вверху.
Ответ №1:
Многие модули в наши дни переписываются таким образом, чтобы их можно было выполнять как на Python 2, так и на Python 3. Оказывается, это совсем не сложно, и в будущем будет очень легко просто отказаться от поддержки Python 2.
Взгляните на модуль six, который помогает с этой задачей, заключая в капсулу многие различия удобным способом:
Six предоставляет простые утилиты для переноса различий между Python 2 и Python 3.
На его веб-сайте (и, конечно, в коде) перечислено множество способов сделать это возможным.
Ответ №2:
Поместите следующий код в py3k.py
модуль и импортируйте его следующим образом: from py3k import *
. Вам нужно поместить его в каждый файл, но вы даже можете оставить его там, если никто больше не использует Python 2.x, или вы могли бы просто выполнить поиск и заменить строку импорта пробелом, а затем удалить файл.
try:
from future_builtins import *
except ImportError:
pass
try:
input = raw_input
range = xrange
except NameError:
pass
И вот как выглядит мой файл шаблона:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
"""
from __future__ import division, absolute_import,
print_function, unicode_literals
from utils.py3k import * # @UnusedWildImport
#
Комментарии:
1. Нет необходимости выполнять nested_scopes, generators, with_statement; все они доступны, когда работают фьючерсы py3. Также zip, map, filter следует импортировать из
future_builtins
вместо этого…2. Спасибо, не знал о
future_builtins
. Что вы подразумеваете под «работой фьючерсов py3»?3.
generators
,with_statement
иnested_scopes
уже есть в 2.6, поэтому они не нужны, потому чтоprint_function
иunicode_literals
будут жаловаться при попытке импорта в 2.5…4. Ах, также только что было отмечено:
from __future__ import
должно быть в каждом файле, это не влияет на другие файлы изpy3k.py
Ответ №3:
Вам также необходимо использовать новые синтаксисы исключений, т.Е. не более
try:
raise Exception, "Message"
except Exception, e:
pass
вместо этого вы должны сделать:
try:
raise Exception("Message")
except Exception as e:
pass
Также убедитесь, что вы добавляете во все свои двоичные строки префикс b, т.Е.:
b’Это двоичная строка’
Более полное описание этого раздела см. http://python3porting.com/noconv.html
Комментарии:
1. Одной из главных неприятностей является отсутствие
u'string'
синтаксиса в 3. За мои деньги ужасное решение.2. @Marcin: Это вернулось в 3.3.
Ответ №4:
Здесь могут оказать большую помощь многие IDE на Python.
PyCharm, например, может быть настроен для проверки совместимости с любым диапазоном версий,
и сообщать о проблемах любого уровня серьезности:
Комментарии:
1. Ninja IDE ( ninja-ide.org ) также имеет аналогичный модуль, который поможет вам преобразовать ваш код в 3.X.
Ответ №5:
try:
input = raw_input
range = xrange
except NameError:
pass
На ум приходят два варианта…
Ответ №6:
Я предлагаю вам попробовать будущую библиотеку. С их сайта:
python-future — это недостающий уровень совместимости между Python 2 и Python 3. Это позволяет использовать единую, чистую, совместимую с Python 3.x кодовую базу для поддержки как Python 2, так и Python 3 с минимальными накладными расходами.
Он предоставляет будущим и прошлым пакетам обратные порты функций из Python 3 и 2. Он также поставляется с настраиваемыми скриптами futurize и pasteurize на основе 2to3, которые помогают вам легко конвертировать Py2 или Py3-код для поддержки Python 2 и 3 в единой чистой кодовой базе в стиле Py3, модуль за модулем.
Известными проектами, использующими python-future для совместимости с Python 2/3, являются Mezzanine и ObsPy.
Ответ №7:
Избегая range()
и zip()
, вместо этого используя xrange()
и itertools.izip()
.
Комментарии:
1. Проблема с использованием
xrange
заключается в том, что он отсутствует в Python 3, поэтому у того же кода нет шансов на выполнение там. Если кто-то готов отказаться от возможных преимуществ в производительностиxrange
, лучше использоватьrange
вместо этого, делая код более совместимым с python 2 и 32. @Eli Почему бы не попробовать (как в моем примере), за исключением того, что range = xrange?
3. @Eli: Но, используя xrange и т.д., вы можете затем тривиально запустить 2to3 в коде, в то время как в противном случае вы могли бы делать что-то вроде
zip(foo)[2]
, что не сработает, поскольку результат в Python 3 не является списком.4. @Lennart: согласен с 2to3. На самом деле все зависит от подхода, используемого для реализации перехода.