在Python distutils中从setup.py中查找脚本目录的正确方法?

时间:2012-10-19 13:40:42

标签: python setuptools distutils setup.py distribute

我正在分发一个具有以下结构的包:

mymodule:
  mymodule/__init__.py
  mymodule/code.py
  scripts/script1.py
  scripts/script2.py

mymodule的{​​{1}}子目录包含代码,mymodule子目录包含应由用户执行的脚本。

scripts中描述软件包安装时,我使用:

setup.py

指定脚本的位置。在安装过程中,它们通常会进入某个平台/用户特定的scripts=['myscripts/script1.py'] 目录。我在bin中的代码需要调用脚本。然后找到这些脚本的完整路径的正确方法是什么?理想情况下,它们应该在用户的路径上,所以如果我想从shell中调用它们,我应该可以这样做:

mymodule/mymodule

但我希望通过其绝对路径调用脚本,而不是依赖于os.system('script1.py args') 上的特定于平台的bin目录,如:

PATH

如何做到这一点?感谢。

编辑删除脚本以外的代码对我来说不是一个实用的解决方案。原因是我将作业分配到集群系统,而我通常这样做的方式是这样的:假设你有一组你想要运行的任务。我有一个脚本,它将所有任务作为输入,然后调用另一个脚本,该脚本仅在给定任务上运行。类似的东西:

# get the directory where the scripts reside in current installation
scripts_dir = get_scripts_dir()
script1_path = os.path.join(scripts_dir, "script1.py")
os.system("%s args" %(script1_path))

所以main.py: for task in tasks: cmd = "python script.py %s" %(task) execute_on_system(cmd) 需要知道main.py的位置,因为它需要是script.py可执行的命令。

3 个答案:

答案 0 :(得分:3)

我认为您应该构建代码,以便不需要从代码中调用脚本。将您需要的代码从脚本移动到包中,然后您可以从脚本和代码中调用此代码。

答案 1 :(得分:1)

我的用例是检查我的脚本安装到的目录是否在用户的路径中,如果没有则发出警告(因为如果用--user安装,它通常不在路径中) 。这是我提出的解决方案:

from setuptools.command.easy_install import easy_install

class my_easy_install( easy_install ):

    # Match the call signature of the easy_install version.
    def write_script(self, script_name, contents, mode="t", *ignored):

        # Run the normal version
        easy_install.write_script(self, script_name, contents, mode, *ignored)

        # Save the script install directory in the distribution object.
        # This is the same thing that is returned by the setup function.
        self.distribution.script_install_dir = self.script_dir

...

dist = setup(...,
             cmdclass = {'build_ext': my_builder,  # I also have one of these.
                         'easy_install': my_easy_install,
                        },
            )

if dist.script_install_dir not in os.environ['PATH'].split(':'):
    # Give a sensible warning message...

我应该指出这是针对setuptools的。如果你使用distutils,那么解决方案是类似的,但略有不同:

from distutils.command.install_scripts import install_scripts

class my_install_scripts( install_scripts ):  # For distutils
    def run(self):
        install_scripts.run(self)
        self.distribution.script_install_dir = self.install_dir

dist = setup(...,
             cmdclass = {'build_ext': my_builder,
                         'install_scripts': my_install_scripts,
                        },
            )

答案 2 :(得分:0)

我认为正确的解决方案是

scripts=glob("myscripts/*.py"),