2010-09-14 3 views
23

Lassen Sie uns das folgende Projekt-Layout übernehmen:Python distutils Fehler: "[Verzeichnis] ​​... ist nicht vorhanden oder nicht, eine normale Datei"

$ ls -R . 
.: 
package setup.py 

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

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

Und den folgenden Inhalt für setup.py:

$ cat setup.py 
from distutils.core import setup 


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

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

Wie Sie sehen können, möchte ich alle Nicht-Python-Dateien in package/ und package/dir/ Verzeichnisse einschließen. Allerdings würde setup.py install läuft erhöhen den folgenden Fehler:

$ 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 

Was soll das?

+0

Eine viel einfachere Lösung in dieser Antwort gegeben: http://stackoverflow.com/a/25375689/74632 –

Antwort

18

In Ihrem package_data entspricht Ihr '*' glob package/dir selbst, und versuchen Sie, dieses Verzeichnis als eine Datei zu kopieren, was zu einem Fehler führt. Suchen Sie ein Klacks, der das Verzeichnis nicht übereinstimmen package/dir, Ihre Umschreiben setup.py entlang dieser Linien:

from distutils.core import setup 

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

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

Bei Ihrem Beispiel, dass nur '*' zu '*.dat' ändert sich, obwohl Sie wahrscheinlich Ihre glob mehr als das brauchen würde, verfeinern , nur sicherstellen, dass es nicht übereinstimmt 'dir'

+6

Ah. Vielen Dank. Weißt du, ob es eine elegantere Art gibt, "alles rekursiv in diesem Paket (oben auf den Modulen)" anzugeben? – Santa

+2

Sie könnten durch die Verwendung einer MANIFEST.in Datei, aber es ist leider schwieriger als ideal (wie diese Suche http://www.google.se/search?q=distutils+package_data+include+directory zeigt, eine Menge von Leute stellen diese Frage, und nicht viele erhalten Antworten). Das umfassendste Dokument ist dies: http://docs.python.org/distutils/setupskript.html, aber es ist nicht sehr klar geschrieben (um Ihr Problem zu finden, ich pdb'd in distutils Quelle) –

+1

Während dies scheint zu sein Die Lösung, es ist schrecklich, dass distributils nicht nur Unterverzeichnisse auspacken können! Dies funktioniert in Windows einwandfrei, schlägt jedoch unter Linux fehl. Ich habe eine umfangreiche Verschachtelung von Unterverzeichnissen und muss explizit definieren, dass dies echte Schmerzen sein wird und schwieriger zu warten ist. – BuvinJ

4

Sie könnten Distribute anstelle von distutils verwenden. Es funktioniert im Grunde das gleiche (zum größten Teil, werden Sie nicht Ihre setup.py sich ändern müssen) und es gibt Ihnen die exclude_package_data Option:

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

ich eine Funktion erstellt, die mir alle Dateien gibt, die ich brauche

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 

und verwendete das als arugment für package_data

0

Nicht ganz sicher, warum, aber nach einiger Fehlersuche, dass ich erkennen die Verzeichnisse umbenennen, die Punkte in ihrem Namen hatte das Problem gelöst. Z.B.

chart.js-2.4.0 => chart_js-2_4_0 

Hinweis: Ich verwende Python 2.7.10, Setuptools 12.2

Verwandte Themen