2013-01-14 5 views
13

Quando si utilizza setuptools/distutils di costruire librerie C in PythonTesting Python C librerie - ottenere costruire il percorso

$ python setup.py build 

i file *.so/*.pyd sono collocati in build/lib.win32-2.7 (o equivalente).

Mi piacerebbe testare questi file nella mia suite di test, ma preferisco non codificare il percorso build/lib*. Qualcuno sa come estrarre questo percorso dalle distutils così posso sys.path.append(build_path) - o c'è un modo ancora migliore per procurarsi questi file? (senza averli installati prima)

+1

L'ho voluto anche in alcune occasioni, ma non sono mai stato abbastanza motivato per cercare una risposta ... – mgilson

risposta

11

È necessario ottenere la piattaforma su cui si sta eseguendo e la versione di python su cui si sta eseguendo e quindi assemblare il nome da soli.

Per ottenere la piattaforma corrente, utilizzare sysconfig.get_platform(). Per ottenere la versione Python, utilizzare sys.version_info (in particolare i primi tre elementi della tupla restituita). Sul mio sistema (64-bit linux con Python 2.7.2) ottengo:

>>> import sysconfig 
>>> import sys 
>>> sysconfig.get_platform() 
linux-x86_64 
>>> sys.version_info[:3] 
(2, 7, 2) 

Il formato della directory lib è "lib.platform-versionmajor.versionminor" (cioè solo 2.7, non 2.7.2) . È possibile costruire questa stringa utilizzando metodi di formattazione stringa di pitone:

def distutils_dir_name(dname): 
    """Returns the name of a distutils build directory""" 
    f = "{dirname}.{platform}-{version[0]}.{version[1]}" 
    return f.format(dirname=dname, 
        platform=sysconfig.get_platform(), 
        version=sys.version_info) 

È possibile utilizzare questo per generare il nome di una qualsiasi delle Distutils directory di compilazione:

>>> import os 
>>> os.path.join('build', distutils_dir_name('lib')) 
build/lib.linux-x86_64-2.7 
+1

Questo è esattamente quello che speravo di non dover fare - ma grazie per la risposta. Forse un giorno riuscirò a scrivere quel fantastico pacchetto di distribuzione Python ... – danodonovan

+1

@danodonovan Sono rimasto deluso quando volevo questa informazione e ho scoperto che dovevo scrivere la funzione di cui sopra. Sembra qualcosa che dovrebbe essere facilmente accessibile attraverso le distutils. Almeno in questo modo è possibile capire il percorso in modo programmatico e non è necessario codificarlo. – SethMMorton

+0

In forma più breve: python -c 'import sys, sysconfig; print ("build/lib. {} - {}. {}". format (sysconfig.get_platform(), * sys.version_info [: 2])) ' – zbyszek

4

ho scoperto che compilando il modulo sul posto è meglio per scopi di test. Per farlo basta usare

python setup.py build_ext --inplace 

Questo compilerà tutti i file ausiliari nella directory temporanea, come al solito, ma il file .so finale sarà messo nella directory corrente.

4

Questo è disponibile come membro build_lib della classe di comando build ed è relativo a dove sarebbe setup.py. Ottenere a quando non si è effettivamente in esecuzione setup è piuttosto sgradevole:

import distutils.dist 
import distutils.command.build 
b = distutils.command.build.build(distutils.dist.Distribution()) 
b.finalize_options() 
print(b.build_lib) 

Personalmente mi piacerebbe andare con la soluzione di SethMMorton, in quanto anche se è potenzialmente fragile, se distutils cambia la posizione della directory di compilazione, sospetto a giocare questo tipo di i trucchi sono ancora più fragili se si modificano le strutture distutils.

+1

Una parola di avvertimento: 'distutils.dist.Distribution()' non sarà sufficiente se, ad esempio, il tuo 'setup.py' crea un'estensione nativa. In tal caso, potrebbe essere necessario creare un 'Distribution' dal proprio metadata dict' setup.py'. – zneak