ユーザーがコマンドを実行できるように、setuptools setup.pyファイルの一部としてインストール後Pythonスクリプトファイルを指定することは可能ですか?
python setup.py install
ローカルプロジェクトファイルアーカイブ、または
pip install <name>
pyPIプロジェクトの場合、スクリプトは標準のsetuptoolsインストールの完了時に実行されますか?単一のPythonスクリプトファイル(たとえば、カスタムポストインストールメッセージをユーザーに配信する、別のリモートソースから追加のデータファイルをプルする)でコーディングできるポストインストールタスクを実行したいリポジトリ)。
私は this SO数年前からの回答 トピックに対処し、その時点でコンセンサスはinstallサブコマンドを作成する必要があるように聞こえます。それでも問題が解決しない場合、ユーザーがスクリプトを実行するために2番目のコマンドを入力する必要がないように、これを行う方法の例を提供することは可能でしょうか?
このソリューションはより透明です:
setup.pyにいくつか追加します。追加のファイルは必要ありません。
また、2つの異なるインストール後を考慮する必要があります。 1つは開発/編集モード用で、もう1つはインストールモード用です。
post-installスクリプトを含む次の2つのクラスをsetup.pyに追加します。
_from setuptools import setup
from setuptools.command.develop import develop
from setuptools.command.install import install
class PostDevelopCommand(develop):
"""Post-installation for development mode."""
def run(self):
# PUT YOUR POST-INSTALL SCRIPT HERE or CALL A FUNCTION
develop.run(self)
class PostInstallCommand(install):
"""Post-installation for installation mode."""
def run(self):
# PUT YOUR POST-INSTALL SCRIPT HERE or CALL A FUNCTION
install.run(self)
_
cmdclass
引数をsetup()
関数にsetup.pyに挿入します。
_setup(
...
cmdclass={
'develop': PostDevelopCommand,
'install': PostInstallCommand,
},
...
)
_
次のように、インストール後にシェルコマンドを呼び出すこともできます。
_from setuptools import setup
from setuptools.command.develop import develop
from setuptools.command.install import install
from subprocess import check_call
class PostDevelopCommand(develop):
"""Post-installation for development mode."""
def run(self):
check_call("apt-get install this-package".split())
develop.run(self)
class PostInstallCommand(install):
"""Post-installation for installation mode."""
def run(self):
check_call("apt-get install this-package".split())
install.run(self)
setup(
...
_
PS setuptoolsには、インストール前のエントリポイントはありません。なぜ存在しないのか疑問に思っているなら、 この議論 を読んでください。
これは、インストール後のスクリプトでパッケージの依存関係が既にインストールされている必要がある場合に私にとって有効な唯一の戦略です。
import atexit
from setuptools.command.install import install
def _post_install():
print('POST INSTALL')
class new_install(install):
def __init__(self, *args, **kwargs):
super(new_install, self).__init__(*args, **kwargs)
atexit.register(_post_install)
setuptools.setup(
cmdclass={'install': new_install},
解決策としては、post_setup.py
in setup.py
のディレクトリ。 post_setup.py
には、ポストインストールを行う関数が含まれ、setup.py
は、適切なタイミングでのみインポートして起動します。
setup.py
:
from distutils.core import setup
from distutils.command.install_data import install_data
try:
from post_setup import main as post_install
except ImportError:
post_install = lambda: None
class my_install(install_data):
def run(self):
install_data.run(self)
post_install()
if __== '__main__':
setup(
...
cmdclass={'install_data': my_install},
...
)
post_setup.py
:
def main():
"""Do here your post-install"""
pass
if __== '__main__':
main()
setup.py
そのディレクトリから、インポートできますpost_setup.py
それ以外の場合は、空の関数を起動します。
post_setup.py
、if __== '__main__':
ステートメントを使用すると、コマンドラインから手動でポストインストールを起動できます。
ポストインストールを実行し、要件を維持する最も簡単な方法は、setup(...)
への呼び出しを修飾することだと思います。
_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=['...
)
)
_
これは、setup
を宣言するときにsetup()
を実行します。要件のインストールが完了すると、_post_install()
関数が実行され、内部関数_post_actions()
が実行されます。
Atexitを使用する場合、新しいcmdclassを作成する必要はありません。 setup()呼び出しの直前にatexitレジスタを作成するだけです。同じことをします。
また、依存関係を最初にインストールする必要がある場合、これはnotを実行します。これは、pipがパッケージを所定の場所に移動する前にatexitハンドラーが呼び出されるためです。
@ Apalala、@ Zulu、@ mertyildiranからの回答を組み合わせます。これはPython 3.5環境で私のために働いた:
import atexit
import os
import sys
from setuptools import setup
from setuptools.command.install import install
class CustomInstall(install):
def run(self):
def _post_install():
def find_module_path():
for p in sys.path:
if os.path.isdir(p) and my_name in os.listdir(p):
return os.path.join(p, my_name)
install_path = find_module_path()
# Add your post install code here
atexit.register(_post_install)
install.run(self)
setup(
cmdclass={'install': CustomInstall},
...
これにより、install_path
にあるパッケージのインストールパスにアクセスして、シェルの作業を行うことができます。