Не трогай мой Шебанг - PullRequest
       50

Не трогай мой Шебанг

25 голосов
/ 07 октября 2009

Одна вещь, которую я ненавижу в отношении distutils (я думаю он - зло, которое делает это ), заключается в том, что это меняет линию Шебанга. Другими словами, более рациональные и среднесрочные решения решаются Писанием

#!/usr/bin/env python

магически преобразуется в

#!/whatever/absolute/path/is/my/python

Это видно и с grok: я использовал grokproject в virtualenv для запуска своего проекта, но теперь я больше не могу перемещать каталог разработки, потому что он помещает абсолютные пути в директиву shebang.

Причина, по которой я спрашиваю это, двоякая

  • Я хочу переместить его, потому что я начал разрабатывать в одном каталоге (эксперименты), и теперь я хочу переместить его по правильному пути, но я не смог этого сделать. Поэтому я создал новый virtualenv и grokproject и скопировал мои файлы. Это решает проблему, но оставляет неудовлетворенным мое любопытство к более рациональному решению. В частности, если бы ссылка на интерпретатор python virtualenv была относительной, проблема не возникла бы в первую очередь. Вы знаете расположение virtualenv и легко можете обратиться к питону virtualenv.
  • Вторая причина в том, что я хотел бы иметь возможность подключить virtualenv к другому компьютеру и запустить его там без проблем. Это невозможно, если у вас жестко закодированные пути.

Ответы [ 5 ]

14 голосов
/ 07 октября 2009

Конечно, вы можете перемещать каталог разработки. Distutils изменяет пути к питону, с которым вы должны работать при запуске. Это в Grok запускается при запуске buildout. Переместите и перезапустите загрузчик и сборку. Готово!

Distutils изменяет путь к Python, который вы используете для запуска distutils. Если этого не произойдет, то вы можете в конечном итоге установить библиотеку в одной версии Python, но при попытке запустить сценарий произойдет сбой, поскольку он будет работать с другой версией Python, у которой нет библиотеки.

Это не безумие, это фактически единственный разумный способ сделать это.

Обновление: Если вы знаете, что делаете, вы можете сделать это:

/path/to/install/python setup.py build -e "/the/path/you/want/python" install

Убедитесь, что вы сначала очистили каталог сборки. :)

10 голосов
/ 12 ноября 2009

Distutils автоматически заменит shebang на местоположение двоичного файла Python, который использовался для запуска setup.py. Чтобы изменить это поведение, у вас есть два варианта:

Вариант 1: вручную

Вы можете передать флаг - исполняемый файл = / path / to / my / python в setup.py. Аргументы принимаются.

Пример:

% python setup.py build --executable=/opt/local/bin/python -d

Вариант 2: автоматически

Другой вариант - добавить строку в setup.cfg. Если вы не используете setup.cfg, создайте его в том же каталоге, что и setup.py. Setup.py ищет это при запуске. Любые параметры, указанные здесь, могут быть переопределены флагами в командной строке.

% cat setup.cfg 
[build]
executable = /opt/local/bin/python -d
2 голосов
/ 07 мая 2012

В одной из последних версий distutils есть флаг - no-autoreq , который работал для меня:

--no-autoreq         do not automatically calculate dependencies

В моем случае я создавал RPM-файлы с исполняемым файлом python2.4 на сервере с версиями 2.4 и 2.6. bdist просто оставил Шебанги такими, какими они были, после запуска:

python setup.py bdist_rpm --no-autoreq

В случае, если вы обрабатываете файлы spec , вы можете использовать решение, описанное в https://stackoverflow.com/a/7423994/722997,, добавив:

AutoReq: no
2 голосов
/ 07 октября 2009

У меня нет решения вашей проблемы, но я вижу некоторое обоснование текущего поведения distutils .

#!/usr/bin/env python выполняет системную версию Python по умолчанию. Это нормально, если ваш код совместим с указанной версией. При обновлении версии по умолчанию (скажем, с 2.5 до 3) ваш код или другой код Python, который ссылается на /usr/bin/env, может перестать работать, даже если старая версия Python все еще установлена. По этой причине имеет смысл «жестко закодировать» путь к соответствующему интерпретатору python.

Редактировать: Вы правы, утверждая, что указание python2.4 или аналогичное решает эту проблему.

Редактировать 2: все не так ясно, когда присутствует несколько установок одной и той же версии Python, как Нед Дейли указывает на комментарии ниже.

1 голос
/ 26 октября 2015

была такая же проблема. попытался вообще найти способ предотвратить касание по умолчанию. вот решение. по сути, мы переопределяем стандартную процедуру копирования скрипта (build_scripts).

в setup.py add

from distutils.command.build_scripts import build_scripts

# don't touch my shebang
class BSCommand (build_scripts):
    def run(self):
        """
        Copy, chmod each script listed in 'self.scripts'
        essentially this is the stripped 
         distutils.command.build_scripts.copy_scripts()
        routine
        """
        from stat import ST_MODE
        from distutils.dep_util import newer
        from distutils import log
        import os

        self.mkpath(self.build_dir)
        outfiles = []
        for script in self.scripts:
            outfile = os.path.join(self.build_dir, os.path.basename(script))
            outfiles.append(outfile)

            if not self.force and not newer(script, outfile):
                log.debug("not copying %s (up-to-date)", script)
                continue

            log.info("copying and NOT adjusting %s -> %s", script,
                         self.build_dir)
            self.copy_file(script, outfile)

        if os.name == 'posix':
            for file in outfiles:
                if self.dry_run:
                    log.info("changing mode of %s", file)
                else:
                    oldmode = os.stat(file)[ST_MODE] & 0o7777
                    newmode = (oldmode | 0o555) & 0o7777
                    if newmode != oldmode:
                        log.info("changing mode of %s from %o to %o",
                                 file, oldmode, newmode)
                        os.chmod(file, newmode)

setup(name="name",
      version=version_string,
      description="desc",
      ...
      test_suite='testing',
      cmdclass={'build_scripts': BSCommand},
      )

.. ede / duply.net

...