webentwicklung-frage-antwort-db.com.de

Führen Sie ein Python-Skript nach der Installation mithilfe von distutils/setuptools aus

Ich versuche, eine Python-Distutils-Aufgabe nach der Installation hinzuzufügen, wie in So erweitern Sie Distutils mit einem einfachen Post-Installationsskript? Beschrieben. Die Task soll ein Python-Skript im installierten lib-Verzeichnis ausführen. Dieses Skript generiert zusätzliche Python-Module, die für das installierte Paket erforderlich sind.

Mein erster Versuch ist wie folgt:

from distutils.core import setup
from distutils.command.install import install

class post_install(install):
    def run(self):
        install.run(self)
        from subprocess import call
        call(['python', 'scriptname.py'],
             cwd=self.install_lib + 'packagename')

setup(
 ...
 cmdclass={'install': post_install},
)

Dieser Ansatz funktioniert, aber soweit ich das beurteilen kann, hat er zwei Mängel:

  1. Wenn der Benutzer einen anderen Python-Interpreter als den von PATH verwendeten verwendet hat, wird das Skript nach der Installation mit einem different - Interpreter ausgeführt, was zu Problemen führen kann.
  2. Es ist nicht ungefährlich gegen Trockenlauf usw., die ich möglicherweise beheben kann, indem ich sie in eine Funktion einwickle und sie mit distutils.cmd.Command.execute aufrufe.

Wie kann ich meine Lösung verbessern? Gibt es dafür einen empfohlenen Weg/eine bewährte Methode? Ich möchte vermeiden, wenn möglich, eine andere Abhängigkeit einzuziehen.

28
kynan

Der Umgang mit diesen Mängeln ist:

  1. Rufen Sie den vollständigen Pfad zum Python-Interpreter ab, der setup.py von sys.executable ausführt.
  2. Klassen, die von distutils.cmd.Command erben (wie beispielsweise distutils.command.install.install, die wir hier verwenden), implementieren die execute-Methode, die eine gegebene Funktion auf "sichere Weise" ausführt, d. H. Unter Beachtung des Trockenlauf-Flags.

    Beachten Sie jedoch, dass die --dry-run-Option derzeit defekt ist und nicht wie beabsichtigt funktioniert.

Ich habe die folgende Lösung gefunden:

import os, sys
from distutils.core import setup
from distutils.command.install import install as _install


def _post_install(dir):
    from subprocess import call
    call([sys.executable, 'scriptname.py'],
         cwd=os.path.join(dir, 'packagename'))


class install(_install):
    def run(self):
        _install.run(self)
        self.execute(_post_install, (self.install_lib,),
                     msg="Running post install task")


setup(
    ...
    cmdclass={'install': install},
)

Beachten Sie, dass ich für meine abgeleitete Klasse den Klassennamen install benutze, da dies python setup.py --help-commands verwendet.

34
kynan

Ich denke, der einfachste Weg, die Nachinstallation durchzuführen und die Anforderungen einzuhalten, besteht darin, den Aufruf an setup(...) zu dekorieren:

from setup tools import setup


def _post_install(setup):
    def _post_actions():
        do_things()
    _post_actions()
    return setup

setup = _post_install(
    setup(
        name='NAME',
        install_requires=['...
    )
)

Dies wird setup() ausgeführt, wenn setup deklariert wird. Sobald die Installation der Anforderungen abgeschlossen ist, wird die Funktion _post_install() ausgeführt, die die innere Funktion _post_actions() ausführt.

1
Mbm