2010-09-14 11 views
23

Prendiamo il seguente layout del progetto:Python Distutils errore: "[directory] ... non esiste o non è un file regolare"

$ ls -R . 
.: 
package setup.py 

./package: 
__init__.py dir file.dat module.py 

./package/dir: 
tool1.dat tool2.dat 

E il seguente contenuto per setup.py:

$ cat setup.py 
from distutils.core import setup 


setup(name='pyproj', 
     version='0.1', 

     packages=[ 
      'package', 
     ], 
     package_data={ 
      'package': [ 
       '*', 
       'dir/*', 
      ], 
     }, 
    ) 

Come puoi vedere, voglio includere tutti i file non Python nelle directory package/ e package/dir/. Tuttavia, l'esecuzione setup.py install solleverebbe il seguente errore:

$ python setup.py install 
running install 
running build 
running build_py 
creating build 
creating build/lib 
creating build/lib/package 
copying package/module.py -> build/lib/package 
copying package/__init__.py -> build/lib/package 
error: can't copy 'package/dir': doesn't exist or not a regular file 

Che cosa dà?

+0

Una soluzione molto più semplice è dato in questa risposta: http://stackoverflow.com/a/25375689/74632 –

risposta

18

Nel tuo package_data, il tuo '*' glob corrisponderà allo stesso package/dir e tenterà di copiarlo come un file, causando un errore. Trova un glob che non corrisponderanno la directory package/dir, riscrivere il setup.py lungo queste linee:

from distutils.core import setup 

setup(name='pyproj', 
     version='0.1', 

     packages=[ 
      'package', 
     ], 
     package_data={ 
      'package': [ 
       '*.dat', 
       'dir/*' 
      ], 
     }, 
    ) 

dato il vostro esempio, questo è solo cambiando '*' a '*.dat', anche se si sarebbe probabilmente bisogno di affinare la glob di più , assicurati che non corrisponda a 'dir'

+6

Ah. Grazie. Sai se c'è un modo più elegante di specificare "include tutto, in modo ricorsivo, in questo pacchetto (in cima ai moduli)"? – Santa

+2

Potresti scappare usando un file MANIFEST.in, ma sfortunatamente è più difficile dell'ideale (dato che questa ricerca http://www.google.se/search?q=distutils+package_data+include+directory mostra, un sacco di le persone stanno facendo questa domanda, e non molte ricevono risposte). Il documento più completo è questo: http://docs.python.org/distutils/setupscript.html, ma non è scritto molto chiaramente (per trovare il tuo problema, io in realtà sono pdb in fonte distutils) –

+1

Mentre questo sembra essere la soluzione, è terribile che le distribuzioni non possano semplicemente gestire sottodirectory fuori dalla scatola! Funziona bene in Windows, ma non funziona in Linux. Ho una vasta nidificazione di sottodirectory e devo definire esplicitamente che sarà una vera sofferenza ed essere più difficile da mantenere. – BuvinJ

4

È possibile utilizzare Distribute anziché le distutils. Funziona praticamente lo stesso (per la maggior parte, non sarà necessario cambiare la vostra setup.py) e ti dà la possibilità exclude_package_data:

from distribute_setup import use_setuptools 
use_setuptools() 

from setuptools import setup 

setup(name='pyproj', 
     version='0.1', 

     packages=[ 
      'package', 
     ], 
     package_data={ 
      'package': [ 
       '*.dat', 
       'dir/*' 
      ], 
     }, 
     exclude_package_data={ 
      'package': [ 
       'dir' 
      ], 
     }, 
    ) 
0

ho creato una funzione che mi dà tutti i file che ho bisogno

def find_files(directory, strip): 
    """ 
    Using glob patterns in ``package_data`` that matches a directory can 
    result in setuptools trying to install that directory as a file and 
    the installation to fail. 

    This function walks over the contents of *directory* and returns a list 
    of only filenames found. The filenames will be stripped of the *strip* 
    directory part. 
    """ 

    result = [] 
    for root, dirs, files in os.walk(directory): 
    for filename in files: 
     filename = os.path.join(root, filename) 
     result.append(os.path.relpath(filename, strip)) 
    return result 

e utilizzato che, come arugment per package_data

0

Non capisco perché, ma dopo un po 'di risoluzione dei problemi mi sono reso conto che rinomina le directory che hanno avuto punti nel loro nome ha risolto il problema. Per esempio.

chart.js-2.4.0 => chart_js-2_4_0 

Nota: sto usando Python 2.7.10, setuptools 12.2

Problemi correlati