shebang env предпочитает версию python

У меня есть скрипты python-2.x, которые я копирую между различными системами, Debian и Arch Linux. Debian устанавливает python как '/ usr / bin / python', а Arch устанавливает его как '/ usr / bin / python2'. Проблема в том, что на Arch linux '/ usr / bin / python' также существует, что относится к python-3.x. Поэтому каждый раз, когда я копирую файл, я должен исправить строку shebang, что немного раздражает.

На Arch я использую

#!/usr/bin/env python2 

Пока на debian я

 #!/usr/bin/env python 

Поскольку «python2» не существует на Debian, есть ли способ передать предпочтительное приложение? Может быть, с расширением оболочки? Я не возражаю, если это зависит, например, от '/ bin / sh'. Следующие были бы хороши, но не работают.

 #!/usr/bin/env python2 python #!/usr/bin/env python{2,} #!/bin/sh python{2,} #!/bin/sh -c python{2,} 

Удручающая вещь заключается в том, что «sh -c python {2,}» работает в командной строке: т.е. он вызывает python2, где доступно, и в противном случае python.

Я бы предпочел не делать ссылку «python2-> python» на Debian, потому что тогда, если я дам скрипт кому-то другому, он не будет запущен. Мне также не хотелось бы, чтобы «python» указывал на python2 на Arch, так как он ломается с обновлениями.

Есть ли чистый способ сделать это без написания обертки?

Я понимаю, что аналогичный вопрос задавали раньше, но я не видел никаких ответов, отвечающих моим граничным условиям 🙂 Условная линия shebang для разных версий Python

— ОБНОВИТЬ

Я взломал уродливое решение оболочки, которое делает эту работу на данный момент.

 #!/bin/bash pfound=false; v0=2; v1=6 for p in /{usr/,}bin/python*; do v=($(python -V 2>&1 | cut -c 7- | sed 's/\./ /g')) if [[ ${v[0]} -eq $v0 && ${v[1]} -eq $v1 ]]; then pfound=true; break; fi done if ! $pfound; then echo "no suitable python version (2.6.x) found."; exit 1; fi $p - $* <<EOF PYTHON SCRIPT GOES HERE EOF 

Объяснение: получить номер версии (v – массив bash) и проверить

 v=($(python -V 2>&1 | cut -c 7- | sed 's/\./ /g')) if [[ ${v[0]} -eq $v0 && ${v[1]} -eq $v1 ]]; then pfound=true; break; fi 

запуск найденной программы $ p с вводом из stdin (-) и аргументов pass ($ *)

 $p - $* <<EOF ... EOF 

4 Solutions collect form web for “shebang env предпочитает версию python”

 #!/bin/sh ''''which python2 >/dev/null 2>&1 && exec python2 "$0" "$@" # ''' ''''which python >/dev/null 2>&1 && exec python "$0" "$@" # ''' ''''exec echo "Error: I can't find python anywhere" # ''' import sys print sys.argv 

Сначала это запускается как сценарий оболочки. Вы можете поместить почти любой код оболочки между '''' и « # ''' . Такой код будет выполнен оболочкой. Затем, когда python запускается в файле, python будет игнорировать строки, так как они выглядят как трикотабельные строки для python.

Скрипт оболочки проверяет, существует ли двоичный путь в пути, с which python2 >/dev/null а затем выполняет его, если это так (со всеми аргументами в нужном месте). Подробнее об этом см. В разделе Почему этот фрагмент с shebang #! / Bin / sh и exec python внутри 4 одинарных кавычек работает?

Примечание. Строка начинается с четырех ' и их должно быть не пустое место между четвертым и началом команды оболочки ( which …)

Что-то вроде этого:

 #!/usr/bin/env python import sys import os if sys.version_info >= (3, 0): os.execvp("python2.7", ["python2.7", __file__]) os.execvp("python2.6", ["python2.6", __file__]) os.execvp("python2", ["python2", __file__]) print ("No sutable version of Python found") exit(2) 

Обновление Ниже приведена более надежная версия.

 #!/bin/bash ok=bad for pyth in python python2.7 python2.6 python2; do pypath=$(type -P $pyth) if [[ -x $pypath ]] ; then ok=$( $pyth <<@@ import sys if sys.version_info < (3, 0): print ("ok") else: print("bad") @@ ) if [[ $ok == ok ]] ; then break fi fi done if [[ $ok != ok ]]; then echo "Could not find suitable python version" exit 2 fi $pyth <<@@ <<< your python script goes here >>> @@ 

Я оставлю это здесь для дальнейшего использования.

Все мои собственные скрипты обычно пишутся для Python 3, поэтому я использую модифицированную версию ответа Aaron McDaid для проверки Python 3 вместо 2:

 #!/usr/bin/env sh ''''which python3 >/dev/null 2>&1 && exec python3 "$0" "$@" # ''' ''''test $(python --version 2>&1 | cut -c 8) -eq 3 && exec python "$0" "$@" # ''' ''''exec echo "Python 3 not found." # ''' import sys print sys.argv 

Я просто набрал

$ which python3

в командной строке и использовал его для поиска линии shebang. Затем я вставляю соответствующую строку shebang.

Я должен сказать, что это развитие – настоящая досада. > 🙁

  • shebang: использовать интерпретатор относительно пути скрипта
  • #! / usr / bin / python и #! / usr / bin / env python, которые поддерживают?
  • Python Script: работает в оболочке, но не работает в реальной жизни, потому что модуль импорта can not
  • Правильный shebang для скрипта Python
  • Невозможно передать аргумент python с помощью «#! / Usr / bin / env python»
  • Python shebang и новые строки
  • Условная строка shebang для разных версий Python
  • запустить скрипт python непосредственно из командной строки
  • Почему virtualenv на Windows не связывает файлы .py / .pyw / .pyo / .pyc с версией исполняемых файлов на виртуальном языке версии Python?
  • Обозначение Shebang: скрипты Python для Windows и Linux?
  • Почему этот фрагмент с shebang #! / Bin / sh и exec python внутри 4 одинарных кавычек работает?
  • Python - лучший язык программирования в мире.