Bash命令在终端中有效,但在python脚本中的“子进程”中无效[重复]
Posted
技术标签:
【中文标题】Bash命令在终端中有效,但在python脚本中的“子进程”中无效[重复]【英文标题】:Bash command works in terminal, but not within 'subprocess' in a python script [duplicate] 【发布时间】:2021-02-20 14:52:32 【问题描述】:我正在尝试使用一些粒子物理软件并在循环中运行它,每次都会稍微改变变量。它具有获取 txt 文件并为此扫描相关命令的特定功能,因此我自然会尝试使用它。我写了一个 python 脚本(最初是用 python3 编写的,可以在我的笔记本电脑上运行,但我需要转移到大学的集群。我已经转换为 python2,因为粒子物理软件本身是 python 2 并试图同时运行两者同时在集群上安装python版本不是我知道该怎么做的事情。特别是集群安装了python2.6.9,我没有任何能力改变它,我也无法更新它或安装新模块。我的问题部分代码是:
def run_madgraph():
# starts madgraph and tells it to run mg5_aMC using mg_run_iridis.txt as a file for it.
print('starting....')
subprocess.check_call(['python', './madgraph/bin/mg5_aMC mg_run_iridis.txt'])
mg5_aMC 启动物理软件,mg_run_iridis.txt 是包含变量信息的文本文件。我不明白为什么这不起作用,因为以下命令在 bash 终端(在集群上)中运行良好:
python ./madgraph/bin/mg5_aMC mg_run_iridis.txt
据我所知,问题出在 python-bash 方面,而不是物理软件中的任何内容。我得到的错误是:
(MGenv) [cb27g11@green0155 Development]$ python MainIridis_script.py
about to run madgraph 1.0 0.9
starting....
python: can't open file '/home/cb27g11/Development/./madgraph/bin/mg5_aMC mg_run_iridis.txt': [Errno 2] No such file or directory
Traceback (most recent call last):
File "/home/cb27g11/Development/MainIridis_script.py", line 41, in <module>
the_main_event()
File "/home/cb27g11/Development/MainIridis_script.py", line 21, in the_main_event
run_madgraph()
File "/home/cb27g11/Development/MainIridis_script.py", line 38, in run_madgraph
subprocess.check_call(['python', './madgraph/bin/mg5_aMC mg_run_iridis.txt'])
File "/home/cb27g11/.conda/envs/MGenv/lib/python3.9/subprocess.py", line 373, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['python', './madgraph/bin/mg5_aMC mg_run_iridis.txt']' returned non-zero exit status 2.
明确一点,/home/cb27g11/Development
,绝对存在:
(MGenv) [cb27g11@green0155 Development]$ pwd
/home/cb27g11/Development
所涉及的各种文件也是如此:
(MGenv) [cb27g11@green0155 Development]$ ls
AD_noCharge_021020.tar.gz NoChar_Allh_1.0_0.9 mg_run_basic.txt
MainIridis_script.py NoChar_Allh_1_0.9 mg_run_iridis.txt
NoCh_h1Only.tar.gz iridis_script.pbs py.py
NoCh_h2Only.tar.gz madgraph
包括mg5_aMC:
(MGenv) [cb27g11@green0155 Development]$ cd madgraph/
(MGenv) [cb27g11@green0155 madgraph]$ cd bin
(MGenv) [cb27g11@green0155 bin]$ ls
mg5 mg5_aMC py.py
我不知道该怎么做,最终不管我怎么做,我仍然需要在另一个脚本(这次是 bash)中调用这个脚本文件才能将它提交到集群。
我不确定是否可以完全避免使用 python 脚本并切换到 bash,我怀疑至少其中一些需要保留在 python 中,但我是物理学家而不是程序员,所以我很容易出错!无论如何,这是完整的脚本:
from __future__ import absolute_import, division, print_function
import numpy as np
import subprocess
import fileinput
tan_beta = np.arange(1, 21.2, 0.2) #Array of tan(beta) values
sin_bma = np.arange(0.9, 1.001, 0.001)#Array of sin(beta-alpha) values
hcm = 1.500000e+05 # Mass of charged Higgses in GeV
textfilepath = 'mg_run_iridis.txt' #path to txt file madgraph will use
Process = 'NoChar_Allh'
def the_main_event():
with open('mg_run_basic.txt','r') as old_card:
text =old_card.read() #stores string of old_card ready for editing
for i in range(0, len(tan_beta)):
tb = tan_beta[i] # loops over tan(beta) values
for j in range(0, len(sin_bma)):
sbma = sin_bma[j] # loops over sin(beta-alpha) values
make_input(tb, sbma, hcm, text)
print('about to run madgraph ' + str(tb) + ' ' + str(sbma))
run_madgraph()
def make_input(Tb, Sbma, Hcm, Text):
# inputs are the value of tan_beta, the value of sin(beta-alpha) values, the desired mass for the charged higgses and a string of text
with open(textfilepath, 'w') as new_card:
#simulation card, the .txt file that gets fed to madgraph
sim_card = Text.replace('TBV', str(Tb))
sim_card = sim_card.replace('SBMAV', str(Sbma))
sim_card = sim_card.replace('HCMV', str(Hcm))
sim_card = sim_card.replace('NAME', str(Process)+'_' + str(Tb) +'_' + str(Sbma))
new_card.write(sim_card) # saves new txt file for madgraph
def run_madgraph():
# starts madgraph and tells it to run mg5_aMC using mg_run_iridis.txt as a file for it.
print('starting....')
subprocess.check_call(['python', './madgraph/bin/mg5_aMC mg_run_iridis.txt'])
the_main_event()
从错误来看,它似乎将 madgraph 可执行文件(我不确定这是否是正确的术语,我的意思是启动 propgram 的文件)作为模块处理?
任何帮助将不胜感激!
【问题讨论】:
我猜米哈伊尔写的是对的。只是一个补充。如果您遇到类似 blablabla “不可调用”之类的错误,那么您应该检查您放置了一些 () 的对象类型,因为这告诉 python 将对象解释为可调用对象,如果对象没有实现 @987654329,python 会抱怨@。在上述情况下,您可以执行help(subprocess)
来查看它是什么类型的对象。
顺便说一句,当你的字符串没有shell指令时,你为什么要使用shell=True
? subprocess.run(['python', './madgraph/bin/mg5_aMC', 'mg_run_iridis.txt'])
效率稍高一些,并且更容易修改参数化值而不会引入安全错误(查找“shell 注入”)。
但最好不要将 Python 作为 Python 的子进程运行。如果你可以import
你想使用的库,那就这样做吧。
@CharlesDuffy 老实说,我不完全确定为什么,但在我的笔记本电脑上,该命令仅适用于添加了 shell=True 的情况。尽管我在 docker 中运行它以避免必须进行 madgraph 的挑剔安装(这是一个基于时间限制的决定,而不是任何事情)。我可能最初应该提到它。在我的笔记本电脑上运行的原始命令是:subprocess.run('sudo docker run -t -i -v $HOME/outputs:/var/MG_outputs --mount type=bind,source=$HOME/models,target=/app hfukuda/madgraph /home/hep/MG5_aMC_v2_6_3_2/bin/mg5_aMC /app/mg_run.txt', shell=True)
列表应该包含三个元素,而不是两个:['python', './madgraph/bin/mg5_aMC', 'mg_run_iridis.txt']
【参考方案1】:
试试:
subprocess.run('python ./madgraph/bin/mg5_aMC mg_run_iridis.txt', shell=True)
注意这个run
部分。有关详细信息,请参阅documentaion。目前,您正在尝试调用 subprocess
模块本身,而不是模块中的特定函数。
【讨论】:
不幸的是,我最初在命令中确实有“运行”,它输出以下内容:Traceback (most recent call last): File "MainIridis_script.py", line 42, in <module> the_main_event() File "MainIridis_script.py", line 22, in the_main_event run_madgraph() File "MainIridis_script.py", line 39, in run_madgraph subprocess.run('python ./madgraph/bin/mg5_aMC mg_run_iridis.txt') AttributeError: 'module' object has no attribute 'run'
根据文档,run
函数是在 Python 3.5 中添加的。你用的是什么 Python 版本?
我在笔记本电脑上使用 python 3,但在大学集群上我遇到了一个问题,因为 madgraph 是用 python 2 编写的,我很难在它们之间切换,所以我只是试图将我的脚本转换为 python2。以上是关于Bash命令在终端中有效,但在python脚本中的“子进程”中无效[重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]