2010-05-17 3 views
7

Vorrei chiamare la funzione di setup() di distonils di Python o setuptools in un modo leggermente anticonvenzionale, ma non sono sicuro se distutils è pensato per questo tipo di utilizzo.Chiamare direttamente la funzione setup() di distutils 'o setuptools' con nome/opzioni del comando, senza analizzare la riga di comando?

Per fare un esempio, diciamo Al momento ho un file 'setup.py', che assomiglia a questo (sollevato testualmente da Distutils docs - l'utilizzo setuptools è quasi identico):

from distutils.core import setup 

setup(name='Distutils', 
     version='1.0', 
     description='Python Distribution Utilities', 
     author='Greg Ward', 
     author_email='[email protected]', 
     url='http://www.python.org/sigs/distutils-sig/', 
     packages=['distutils', 'distutils.command'], 
    ) 

Normalmente , per creare solo il file .spec per un RPM di questo modulo, potrei eseguire python setup.py bdist_rpm --spec-only, che analizza la riga di comando e chiama il codice 'bdist_rpm' per gestire il materiale specifico di RPM. Il file .spec finisce in "./dist".

Come posso modificare la mia chiamata di setup() in modo che esegua il comando 'bdist_rpm' con l'opzione '--spec-only', SENZA l'analisi dei parametri della riga di comando? Posso passare il nome e le opzioni del comando come parametri da configurare()? Oppure posso costruire manualmente una riga di comando e passarla come parametro, invece?

NOTA: so già che potrei chiamare lo script in un processo separato, con una riga di comando vera e propria, usando os.system() o il sottoprocesso modulo o qualcosa di simile. Sto cercando di evitare di utilizzare qualsiasi tipo di richiamo di comandi esterni. Sto cercando specificamente una soluzione che esegua setup() nell'interprete corrente.

Per lo sfondo, sto convertendo alcuni script di shell di gestione della release in un singolo programma Python. Una delle attività è eseguire 'setup.py' per generare un file .spec per ulteriori test preliminari. L'esecuzione di "setup.py" come comando esterno, con le proprie opzioni della riga di comando, sembra un metodo scomodo e complica il resto del programma. Sento che potrebbe esserci un modo più pitonico.

+0

Mi piace la domanda. Per me sembra che 'setup()' sia progettato male - dovrebbe almeno prendere 'sys.argv' come argomento invece di eseguire un po 'di magia. Il parametro può anche essere predefinito a 'sys.argv' (come in' argparse'), ma dovrebbe essere sia documentato che visibile nella firma della funzione. – abukaj

risposta

9

mai provato questo, ma mi è accaduto di guardare in Distutils/core.py, dove ho notato questo in prossimità della partenza della setup():

if 'script_name' not in attrs: 
    attrs['script_name'] = os.path.basename(sys.argv[0]) 
if 'script_args' not in attrs: 
    attrs['script_args'] = sys.argv[1:] 

Così, sembra come se ci riesci "fake-out "setup() con l'aggiunta di:

setup(
    ... 
    script_name = 'setup.py', 
    script_args = ['bdist_rpm', '--spec-only'] 
) 
+0

@ ig0775: Grazie, è esattamente quello che volevo fare. L'ho appena testato e funziona perfettamente. Anche abbastanza pulito. –

1

Basta "falsi" i parametri da riga di comando - per esempio, si avvia script con

import sys 

sys.argv[1:] = ['bdist_rpm', '--spec-only'] 

from distutils.core import setup 

setup(name='Distutils', 

ecc. Ecc. Dopo tutto, è così che distutils ottiene i parametri della riga di comando: appare in sys.argv! Quindi, imposta sys.argv esattamente come desideri e qualsiasi riga di comando che l'utente errato digitato verrà completamente ignorata.

In realtà, si potrebbe desiderare di controllare se l'utente ha fatto inserire qualsiasi argomento che si sta per ignorare - len(sys.argv) > 1 prima di modificare sys.argv - e dare un avvertimento, o evitare l'alterazione del sys.argv, o "Unisci" ciò che l'utente ha digitato, ecc ... ma è molto diverso da quello che hai effettivamente chiesto, quindi ho intenzione di lasciarlo a quello ;-).

+0

Mi era venuto in mente, ma sembrava un po 'disordinato.Ma se non fosse per il metodo di @ ig0774, probabilmente sarebbe come gestirlo. –

+0

@ RyanB.Lynch: * sembrava un po 'disordinato * - La cosa triste e triste è che la routine' run_setup' di Distutils e Setup Tools fa esattamente questo, solo con un po 'di ciliegina sulla parte superiore. Puoi vedere questo, ad es. [Qui] (http://github.com/pypa/setuptools/blob/master/setuptools/sandbox.py) nelle fonti (cerca 'run_setup'). – Wrzlprmft