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

在Python distutils中从setup.py查找脚本目录的正确方法?,python,setuptools,distutils,setup.py,distribute,Python,Setuptools,Distutils,Setup.py,Distribute,我正在分发一个具有以下结构的包: mymodule: mymodule/__init__.py mymodule/code.py scripts/script1.py scripts/script2.py mymodule的mymodule子目录包含代码,scripts子目录包含应由用户执行的脚本 在setup.py中描述软件包安装时,我使用: scripts=['myscripts/script1.py'] 指定脚本应该放在哪里。在安装过程中,它们通常会进入特定于平台/用户

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

mymodule:
  mymodule/__init__.py
  mymodule/code.py
  scripts/script1.py
  scripts/script2.py
mymodule
mymodule
子目录包含代码,
scripts
子目录包含应由用户执行的脚本

setup.py
中描述软件包安装时,我使用:

scripts=['myscripts/script1.py']
指定脚本应该放在哪里。在安装过程中,它们通常会进入特定于平台/用户的
bin
目录。我在
mymodule/mymodule
中的代码需要调用脚本。找到这些脚本的完整路径的正确方法是什么?理想情况下,它们应该位于用户的路径上,因此如果我想从shell中调用它们,我应该能够执行以下操作:

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

# 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
在哪里,因为它需要是一个可由
execute\u on\u系统执行的命令

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

我的用例是检查我的脚本安装到的目录是否在用户路径中,如果不在,则给出警告(因为如果使用--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,
                        },
            )

相关:系统上执行的
execute()
是什么样子?@PiotrDobrogost:
execute\u on\u system
将与shell命令相对应的字符串作为输入。然后,它创建一个名为
cmd.sh
的临时文件,并将命令和必要的前缀放在其中,这些前缀说明作业应该如何运行(特定于用户系统上使用的集群系统)——例如作业应该进入的队列等。然后它接受该脚本
cmd.sh
,并以特定于系统的方式执行它,例如,通过这样做:
os.system(“qsub cmd.sh”)
问题似乎源于您坚持从
cmd.sh
shell脚本运行Python脚本。如果我了解以上内容,请将
cmd.sh
脚本传输到目标机器,任务将在那里运行。你不能以同样的方式传输
script.py
以便知道此脚本在目标计算机上的位置吗?我喜欢这个想法,但实际上它对我不起作用。我在你的工作流中没有看到阻止将某些代码从脚本移到包中的内容。我需要能够生成一个调用Python脚本的命令,这是我包裹的一部分。类似于“python myscript.py someargs”。因此,我需要知道myscript.py住在哪里。。。即使myscript.py是包的一部分,而不是scripts目录中,我仍然需要使用类似
\uuuu file\uuuu
的黑客来找出脚本的位置。从设计的角度来看,这比试图找出脚本目录的位置更可取吗?两种解决方案似乎都不雅观