Есть ли простой способ проверить, совместим ли мой скрипт на python 3.6 с python 2.7?

#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 и выше. Подпроцесс выполняет надлежащее создание, удаление и обработку ошибок.