2009-10-07 14 views
21

Una cosa que odio de distutils (supongo he is the evil who does this) es que cambia la línea shebang. En otras palabras, las más racionales y con el medio ambiente VARs decidieron escrituraNo toques mi shebang

#!/usr/bin/env python 

obtiene mágicamente transformado en

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

Esto se ve también con grok: Solía ​​grokproject en un virtualenv para iniciar mi proyecto, pero ahora ya no puedo mover el directorio de desarrollo porque pone rutas absolutas en la directiva shebang.

La razón por la que pido esto es doble

  • quiero moverlo porque empecé a desarrollar en un directorio (Experimentos) y ahora quiere moverse en un camino correcto, pero no pude hazlo. Así que creé un nuevo virtualenv y grokproject y copié mis archivos. Eso soluciona el problema, pero deja insatisfecha mi curiosidad por una solución más racional. En particular, si la referencia al intérprete virtualenv python fuera relativa, el problema no habría estado presente en primer lugar. Conoces el diseño del virtualenv y puedes consultar el virtualenv python fácilmente.
  • La segunda razón es que me gustaría poder copiar el virtualenv a otra computadora y ejecutarlo sin problemas. Esto no es posible si tiene rutas codificadas.
+3

@Lennart: Porque me parece bastante molesto que todas mis cosas instalado tiene una dependencia muy fuerte y dolorosa contra una ruta específica de mi sistema de archivos, en particular cuando existe una alternativa. –

+0

¿Así que quieres moverlo, solo porque no es obvio cómo? :-) Oooookay ... –

+0

@Lennart: agregado a la pregunta. –

Respuesta

13

Por supuesto, puede mover el directorio de desarrollo alrededor. Distutils cambia las rutas a la python con la que debe ejecutar cuando la ejecuta. Está en ejecución de Grok cuando ejecutas el buildout. Mueva y vuelva a ejecutar el arranque y el buildout. ¡Hecho!

Distutils cambia la ruta de Python que usa para ejecutar distutils. Si no fuera así, podría terminar instalando una biblioteca en una versión de Python, pero cuando intente ejecutar el script fallaría, porque se ejecutaría con otra versión de Python que no tenía la biblioteca.

Eso no es locura, de hecho es la única forma sensata de hacerlo.

Actualización: Si sabe lo que está haciendo, usted puede hacer esto:

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

Asegúrese de limpiar el directorio de construcción primero sin embargo. :)

+0

Tienes un punto. Sin embargo, creo que debería haber la posibilidad de omitir esta transformación, si realmente lo desea. –

+1

Puede hacerlo, si lo instala como archivos de datos en lugar de como un script. Pero esto se interrumpirá tan pronto como lo instale en un sistema que no se ve exactamente como el suyo. –

2

tengo ninguna solución a su problema, pero noto cierta justificación para el comportamiento actual de distutils.

#!/usr/bin/env python ejecuta la versión de Python predeterminada del sistema. Eso está bien siempre y cuando su código sea compatible con dicha versión. Cuando se actualiza la versión predeterminada (de 2.5 a 3, por ejemplo) su código u otro código de Python que hace referencia a /usr/bin/env puede dejar de funcionar, incluso si la versión anterior de Python aún está instalada. Por esa razón, tiene sentido "codificar" la ruta al intérprete apropiado de Python.

Edite: tiene la razón al afirmar que la especificación de python2.4 o similar resuelve este problema.

Edición 2: las cosas no son tan clara cuando varias instalaciones de la misma versión de Python están presentes, como Ned Deily señala en los comentarios a continuación.

+0

puede usar python24. El hecho es que cuando tienes un virtualenv, te gustaría poder moverlo si así lo decides. Una ruta relativa sería mejor, ya que cuando creas el virtualenv, todo está contenido en ese directorio, y todo puede referirse relativo. –

+0

No tengo experiencia con distutils. Su pregunta cita '#!/Usr/bin/env python' en lugar de' #!/Usr/bin/env python2.4'. ¿Cuál de estos especificó en su código? ¿Distutils también realiza la reescritura si se especifica el número de versión? – Stephan202

+0

En algunos sistemas, no es inusual tener más de una instancia de la * misma * versión de python instalada; en este sistema, tengo 3 versiones de python2.5 y eso no cuenta virtualenvs. Como señala Lennart, los scripts se instalan y se vinculan a una instalación de intérprete en particular. Es por eso que, en el caso más general, las rutas relativas de shebang no garantizan un comportamiento correcto. –

8

Distutils reemplazará automáticamente el shebang con la ubicación del binario de Python que se utilizó para ejecutar setup.py. Para anular este comportamiento tiene dos opciones:

Opción 1: manual de

puede pasar la bandera --executable =/ruta/a/mi/python setup.py a. Los argumentos son aceptados.

Ejemplo:

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

Opción 2: Automáticamente

Su otra opción es añadir una línea a setup.cfg. Si no está utilizando setup.cfg, créelo en el mismo directorio que setup.py. Setup.py busca esto en el inicio. Todas las opciones especificadas aquí pueden anularse con banderas en la línea de comandos.

% cat setup.cfg 
[build] 
executable = /opt/local/bin/python -d 
+0

Gracias por esto. Esto es asombroso No puedo encontrar esto documentado en ningún lado. ¿Te importa publicar algunos enlaces de documentación? –

+0

'python setup.py build --help';) – jathanism

+0

¿Hay algo similar para' python setup.py develop'? Mi configuración virtualenv da como resultado algunas rutas muy largas de shebang que causan 'errores de intérprete 'cuando intentan ejecutarlas. Intenté 'sys.executable = '/ usr/bin/env python'' desde el script, pero el espacio parece causar distutils para poner comillas en el shebang, lo que rompe las cosas de una manera diferente. –

1

En una de las últimas versiones de distutils, hay una bandera --no-autoreq que han trabajado para mí:

--no-autoreq   do not automatically calculate dependencies 

En mi caso, yo estaba creando RPM archivos con el ejecutable python2.4, en un servidor con instalaciones 2.4 y 2.6. bdist acaba de dejar los shebangs como estaban, después de correr:

python setup.py bdist_rpm --no-autoreq 

En el caso de que usted está manejando los archivos de especificaciones, es posible utilizar la solución explicada en https://stackoverflow.com/a/7423994/722997, añadiendo:

AutoReq: no 
1

tenía el mismo problema Intenté encontrar una forma de evitar tocar por completo de manera predeterminada. aquí está la solución. esencialmente reemplazamos la rutina de copia de scripts predeterminada (build_scripts).

en setup.py añadir

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

Cuestiones relacionadas