correct way to find scripts directory from setup.py in Python distutils?

梦想与她 提交于 2019-12-23 08:33:34

问题


I am distributing a package that has this structure:

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

The mymodule subdir of mymodule contains code, and the scripts subdir contains scripts that should be executable by the user.

When describing a package installation in setup.py, I use:

scripts=['myscripts/script1.py']

To specify where scripts should go. During installation they typically go in some platform/user specific bin directory. The code that I have in mymodule/mymodule needs to make calls to the scripts though. What is the correct way to then find the full path to these scripts? Ideally they should be on the user's path at that point, so if I want to call them out from the shell, I should be able to do:

os.system('script1.py args')

But I want to call the script by its absolute path, and not rely on the platform specific bin directory being on the PATH, as in:

# 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))

How can this be done? thanks.

EDIT removing the code outside of a script is not a practical solution for me. the reason is that I distribute jobs to a cluster system and the way I usually do it is like this: imagine you have a set of tasks you want to run on. I have a script that takes all tasks as input and then calls another script, which runs only on the given task. Something like:

main.py:
for task in tasks:
  cmd = "python script.py %s" %(task)
  execute_on_system(cmd)

so main.py needs to know where script.py is, because it needs to be a command executable by execute_on_system.


回答1:


I think you should structure your code so that you don't need to call scripts from you code. Move code you need from scripts to your package and then you can call this code both from your scripts and from your code.




回答2:


My use case for this was to check that the directory my scripts are installed into is in the user's path and give a warning if not (since it is often not in the path if installing with --user). Here is the solution I came up with:

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...

I should point out that this is for setuptools. If you use distutils, then the solution is similar, but slightly different:

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,
                        },
            )


来源:https://stackoverflow.com/questions/12975540/correct-way-to-find-scripts-directory-from-setup-py-in-python-distutils

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!