Не трогайте мой shebang
Одна вещь, которую я ненавижу distutils (я думаю он злой, кто это делает) заключается в том, что он меняет линию shebang. Другими словами, более рациональные и экологические варны приняли решение о писании
#!/usr/bin/env python
магически преобразуется в
#!/whatever/absolute/path/is/my/python
Это также видно с помощью grok: я использовал grokproject в virtualenv для запуска моего проекта, но теперь я больше не могу перемещать каталог разработки, потому что он устанавливает абсолютные пути в директиве shebang.
Причина, по которой я задаю это, двоякая.
- Я хочу переместить его, потому что я начал развиваться в одном каталоге (Experiments), и теперь я хочу переместить его в правильный путь, но я не мог этого сделать. Поэтому я создал новый virtualenv и grokproject и скопировал мои файлы. Это устраняет проблему, но оставляет мое любопытство для более рационального решения неудовлетворенным. В частности, если ссылка на виртуальный интерпретатор python была относительной, проблема не была бы в первую очередь. Вы знаете макет виртуального, и вы можете легко обращаться к виртуальному python.
- Вторая причина заключается в том, что я хотел бы иметь возможность scp virtualenv на другой компьютер и запускать его там без проблем. Это невозможно, если у вас есть жестко заданные пути.
Ответы
Ответ 1
Конечно, вы можете перемещать каталог разработки. Distutils изменяет пути к питону, с которым вы должны работать, когда запускаете его. Он запускается в Grok при запуске сборки. Переместите и перезапустите бутстрап и сборку. Готово!
Distutils изменяет путь к Python, который вы используете для запуска distutils. Если это не так, тогда вы можете установить библиотеку в одной версии python, но при попытке запустить script она завершится неудачно, потому что она будет работать с другой версией python, у которой не было библиотеки.
Это не безумие, это на самом деле единственный разумный способ сделать это.
Обновление:
Если вы знаете, что делаете, вы можете сделать это:
/path/to/install/python setup.py build -e "/the/path/you/want/python" install
Сначала убедитесь, что вы очистите каталог сборки.:)
Ответ 2
Distutils автоматически заменит shebang на местоположение двоичного кода Python, который использовался для выполнения setup.py. Чтобы отменить это поведение, у вас есть два варианта:
Вариант 1: вручную
Вы можете передать флаг - executable =/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
Ответ 3
У меня нет решения вашей проблемы, но я вижу некоторое обоснование текущего поведения distutils.
#!/usr/bin/env python
выполняет стандартную версию Python по умолчанию. Это нормально, если ваш код совместим с указанной версией. Когда версия по умолчанию обновляется (от 2.5 до 3, скажем), ваш код или другой код Python, ссылки на /usr/bin/env
могут перестать работать, хотя старая версия Python все еще установлена. По этой причине имеет смысл "жестко кодировать" путь к соответствующему интерпретатору python.
Изменить: вы правы в утверждении, что указание python2.4
или аналогичное решение решает эту проблему.
Изменить 2: все не так ясно, когда присутствуют несколько установок одной и той же версии Python, поскольку Ned Deily указывает на комментарии ниже.
Ответ 4
В одной из последних версий distutils существует флаг - no-autoreq, который работал у меня:
--no-autoreq do not automatically calculate dependencies
В моем случае я создавал RPM файлы с исполняемым файлом python2.4 на сервере с установками 2.4 и 2.6. bdist просто оставил shebangs, как они были, после запуска:
python setup.py bdist_rpm --no-autoreq
В случае, если вы обрабатываете файлы spec, вы можете использовать решение, описанное в fooobar.com/questions/242256/..., добавив:
AutoReq: no
Ответ 5
была та же проблема. попытался найти способ предотвратить трогание по умолчанию. вот решение. по существу мы переопределяем стандартную процедуру копирования script (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
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