#python
#python
Вопрос:
Я ищу способ проверить, будет ли код, разработанный на Python 3.6, совместим с Python 2.7. В идеале — если нет, я хотел бы каким-то образом указать на недопустимый синтаксис. Спасибо
Комментарии:
1. Нет никакого способа предоставить гарантию. Сложные части — это не синтаксис.
2. Если
3to2
выдает идентичный скрипт, то шансы есть.3. помимо синтаксиса или функций, которые могут отличаться или отсутствовать у 2 vs 3, тестирование — это то, что вы должны включить в свой цикл разработки. Тогда вы будете знать. Также помог бы статический анализ.
4. Насколько очевидного «просто запустите его с помощью 2.7» недостаточно для вашего варианта использования? Вас интересует только синтаксис или также стандартная библиотека?
Ответ №1:
Да. Выполните свой код с помощью python2.7 yourScript.py
. Если некоторым модулям нужен python3.*, вы могли бы написать второй скрипт только для python2.7? Халтурно, но это быстрое и ленивое решение.
Вам обязательно следует проверить версию при запуске. Этот фрагмент автоматически перезапускает скрипт с правильной версией:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# pythonVersionCheck.py
import sys
import os
# Color codes for output
CRED = '33[91m'
CGREEN = '33[92m'
CEND = '33[0m'
# Desired python version number
scriptVersion = "3.6"
# Check if script is executed with root. Get rid of this block if you don't need it
if os.geteuid() != 0:
print(CRED "nRestart the script with root privileges: 'sudo python"
scriptVersion " " sys.argv[0] "'n" CEND)
sys.exit(0)
# Check if the script is running with the desired python version
if sys.version[:3] == scriptVersion:
print(CGREEN "Script running with Python " scriptVersion CEND)
else:
print(CRED "Script not running with Python " scriptVersion ". Restarting." CEND)
try:
os.execv(sys.executable, ['python' scriptVersion] sys.argv)
except OSError as error:
print(CRED "An error occured: " str(error) CEND)
# YOUR CODE HERE
Прочитайте о переносимости между Python2.* и Python3. * здесь.
РЕДАКТИРОВАТЬ: По предложению @MisterMiyagi, здесь внесены некоторые изменения.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# pythonVersionCheck.py
import sys
import subprocess
import platform
# Desired python version number
scriptVersion = "2.7"
usedVersion = "{0}.{1}".format(sys.version_info.major,sys.version_info.minor)
opSys = platform.system()
# Check if the script is running with the desired python version
if usedVersion == scriptVersion:
print("Script running with Python " scriptVersion)
else:
print("Script not running with Python " scriptVersion ". Restarting.")
if opSys == 'Linux' or opSys == 'Darwin':
subprocess.call('python' scriptVersion ' ' sys.path[0] '/'
sys.argv[0], shell=True)
elif opSys is 'Windows':
print("py -" scriptVersion ' ' sys.argv[0])
subprocess.call("py -" scriptVersion ' ' sys.argv[0], shell=True)
else:
print("Can't detect os.")
# YOUR CODE HERE
Теперь он использует subprocess
вместо os.execv
.
Теперь он использует sys.version_info
вместо sys.version
.
Теперь он проверяет, на какой платформе работает пользователь, поэтому теперь он переносим на Linux, Windows и Appletoshwin.
Комментарии:
1. Спрашиваю просто из любопытства, есть ли причина, по которой вы пишете
str("3.6")
вместо just"3.6"
? Помогает ли это чему-нибудь, является ли это каким-либо соглашением или просто личной привычкой?2. Спасибо, что указали на это. В данном случае это не имеет значения, вы абсолютно правы!
>>> scriptVersion = str("3.6") >>> type(scriptVersion) <class 'str'> >>> scriptVersion = "3.6" >>> type(scriptVersion) <class 'str'>
3. Пожалуйста, не обращайтесь с переносимостью подобным образом! 1) Это только для UNIX, в Windows это невозможно. 2) Он работает только для поиска путей, без учета виртуальных сред и тому подобного. 3) Отсутствие привилегий — это ошибка, код выхода 0 не подходит. 4) Он не проверяет (и не может), запрашивал ли пользователь явно другую версию Python. 5) Он откажется запускаться в совместимых версиях, таких как 3.7, 3.8, …. 6). 6) Использование
sys.version
иos.execv
является архаичным для этой проблемы. Используйтеsys.version_info
иsubprocess
. Не выполняйте пользовательскую обработку ошибок, которая проглатывает детали.4. @MisterMiyagi Спасибо за критику. Я не знаю, как учитывать виртуальные среды, и для # 4, я думаю, целью было установить номер версии, который следует использовать для скрипта, чтобы пользователь автоматически запускал нужную. Я опубликую правку с помощью
sys.version_info
иsubprocess
через минуту. Не могли бы вы объяснить, почему их использование лучше?5. @anonjnr sys.version_info предоставляет namedtuple, так что вы действительно можете выполнить числовое сравнение major / minor / patch. sys.version_info[:3] >= (3,6,0) будет поддерживать 3.6, 3.7 и так Далее, даже гипотетический 3.10 и выше. Подпроцесс выполняет надлежащее создание, удаление и обработку ошибок.