在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
的黑客来找出脚本的位置。从设计的角度来看,这比试图找出脚本目录的位置更可取吗?两种解决方案似乎都不雅观