2009-10-07 9 views
21

Una cosa che odio di distutils (suppongo che sia he is the evil who does this) è che cambia la linea dello shebang. In altre parole, le più razionali e rispettosi Vars deciso ScritturaNon toccare il mio shebang

#!/usr/bin/env python 

viene magicamente trasformato in

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

Questo è visto anche con Grok: ho usato grokproject in un virtualenv per iniziare il mio progetto, ma ora non posso più spostare la directory di sviluppo, perché pone percorsi assoluti nella direttiva shebang.

Il motivo per cui lo chiedo è duplice

  • voglio spostarlo perché ho iniziato a sviluppare in una directory (Experiments) e ora voglio spostarlo in un percorso corretto, ma non ho potuto fallo. Così ho creato un nuovo virtualenv e grokproject e ho copiato i miei file. Questo risolve il problema, ma lascia la mia curiosità per una soluzione più razionale insoddisfatta. In particolare, se il riferimento all'interprete virtualenv python fosse relativo, il problema non sarebbe stato presente in primo luogo. Conosci il layout di virtualenv e puoi facilmente fare riferimento a virtualenv python.
  • Il secondo motivo è che mi piacerebbe poter scpare il virtualenv su un altro computer ed eseguirlo senza problemi. Questo non è possibile se hai percorsi hardcoded.
+3

@Lennart: Perché trovo piuttosto fastidioso che tutta la mia roba installato ha una dipendenza molto forte e dolorosa contro un percorso specifico del mio filesystem, in particolare quando esiste un'alternativa. –

+0

Quindi vuoi muoverlo, solo perché non è ovvio come? :-) Oooookay ... –

+0

@Lennart: aggiunto alla domanda. –

risposta

13

Ovviamente è possibile spostare la directory di sviluppo in giro. Distutils cambia i percorsi del python che dovresti eseguire quando lo esegui. È in esecuzione Grok quando si esegue il buildout. Sposta e riesegui il bootstrap e il buildout. Fatto!

Distutils cambia il percorso del Python che si utilizza per eseguire distutils con. In caso contrario, si potrebbe finire per installare una libreria in una versione python, ma quando si tenta di eseguire lo script fallirebbe, perché sarebbe eseguito con un'altra versione python che non aveva la libreria.

Questa non è follia, è in realtà l'unico modo per farlo.

Aggiornamento: Se si sa cosa si sta facendo, si può fare questo:

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

Assicurarsi di pulire la directory di compilazione prima però. :)

+0

Hai un punto. Tuttavia, penso che dovrebbe esserci la possibilità di saltare questa trasformazione, se proprio lo vuoi. –

+1

Può, se lo si installa come file di dati anziché come uno script. Ma questo si romperà non appena lo installerai su un sistema che non assomiglia esattamente al tuo. –

2

mi hanno alcuna soluzione al vostro problema, ma lo faccio vedere qualche logica per il comportamento attuale del distutils.

#!/usr/bin/env python esegue la versione predefinita di Python del sistema. Questo va bene finché il tuo codice è compatibile con quella versione. Quando la versione di default viene aggiornata (da 2,5 a 3, per esempio) il tuo codice o altro codice Python che fa riferimento a /usr/bin/env potrebbe smettere di funzionare, anche se la vecchia versione di Python è ancora installata. Per questo motivo ha senso "hardcode" il percorso dell'interprete python appropriato.

Modifica: si ha ragione nel sostenere che la specifica di python2.4 o simili risolve questo problema.

Modifica 2: Le cose non sono così chiare quando sono presenti più installazioni della stessa versione di Python, come Ned Deily indica nei commenti seguenti.

+0

puoi usare python24. Il fatto è che quando hai un virtualenv, ti piacerebbe essere in grado di muoverlo se lo decidi tu. Un percorso relativo sarebbe migliore, dal momento che quando crei il virtualenv, tutto è contenuto in quella dir, e tutto può essere riferito relativo. –

+0

Non ho esperienza con le distutils. La tua domanda cita '#!/Usr/bin/env python' invece di' #!/Usr/bin/env python2.4'. Quale di questi hai specificato nel tuo codice? Le distutils eseguono anche la riscrittura se il numero di versione è specificato? – Stephan202

+0

Su alcuni sistemi non è insolito avere più di una istanza della * stessa * versione di python installata; su questo sistema, mi capita di avere 3 versioni di python2.5 e che non conta virtualenvs. Come sottolinea Lennart, gli script vengono installati e collegati a una particolare installazione di interprete. Ecco perché, nel caso più generale, i percorsi relativi allo shebang non garantiscono un comportamento corretto. –

8

Distutils sostituirà automaticamente lo shebang con il percorso del binario Python utilizzato per eseguire setup.py. Per ignorare questo comportamento si hanno due opzioni:

Opzione 1: manualmente

si può passare la bandiera --executable =/path/to/mio/python a setup.py. Gli argomenti sono accettati.

Esempio:

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

Opzione 2: Automaticamente

L'altra opzione è quella di aggiungere una riga al setup.cfg. Se non si utilizza setup.cfg, crearlo nella stessa directory di setup.py. Setup.py cerca questo all'avvio. Qualsiasi opzione qui specificata può ancora essere sostituita con flag sulla riga di comando.

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

Grazie per questo. Questo e spettacolare. Non riesco a trovare questo documentato ovunque. Cura di pubblicare alcuni collegamenti alla documentazione? –

+0

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

+0

Esiste qualcosa di simile per' python setup.py develop'? Il mio setup di virtualenv ha dei percorsi di shebang molto lunghi che causano errori di 'badintereter' quando si tenta di eseguirli. Ho provato 'sys.executable = '/ usr/bin/env python'' all'interno dello script, ma lo spazio sembra causare distutils per inserire virgolette nello shebang, che spezza le cose in un modo diverso. –

1

In una delle ultime versioni di distutils, c'è una bandiera --no-autoreq che hanno funzionato per me:

--no-autoreq   do not automatically calculate dependencies 

Nel mio caso, stavo creando RPM file con eseguibile python2.4, in un server con installazioni 2.4 e 2.6. bdist appena lasciato i SheBangs come erano, dopo l'esecuzione:

python setup.py bdist_rpm --no-autoreq 

Nel caso in cui si gestisce i file spec, è possibile utilizzare la soluzione spiegato https://stackoverflow.com/a/7423994/722997, aggiungendo:

AutoReq: no 
1

ha avuto lo stesso problema ha cercato di trovare un modo per evitare del tutto il toccare di default. ecco la soluzione. essenzialmente sostituiamo la routine di copia di script predefinita (build_scripts).

in setup.py aggiungere

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

Problemi correlati