将一个Bash脚本转换为Python(小型脚本)

12

我有一个在Linux环境下使用的bash脚本,但现在我需要在Windows平台上使用它,并想将其转换为可以运行的Python脚本。

这个bash脚本相当简单(我认为),我已经尝试通过谷歌来转换它,但无法成功。

这个bash脚本看起来像这样:

runs=5

queries=50

outfile=outputfile.txt

date  >> $outfile


echo -e "\n---------------------------------"
echo -e "\n----------- Normal --------------"
echo -e "\n---------------------------------"
echo -e "\n----------- Normal --------------" >> $outfile
for ((r = 1; r < ($runs + 1); r++))
do
    echo -e "Run $r of $runs\n"

    db2 FLUSH PACKAGE CACHE DYNAMIC

    python reads.py -r1 -pquery1.sql -q$queries -shotelspec -k6 -a5 >> $outfile
done

主要命令是python read.py...等等,它是另一个我得到的Python文件,并且具有如您所见的参数。

我知道这是很大的请求,但如果有人能够将其转换为我可以使用的Python脚本,或者至少给我一些提示和指导,那对我来说真的会很有帮助。

此致

Mestika

根据请求添加:

这是我写的,但没有成功:

runs=5
queries=50
outfile=ReadsAgain.txt
file = open("results.txt", "ab")

print "\n---------------------------------"
print "\n----------- Normal --------------"
print "\n---------------------------------"
file.write("\n----------- Normal --------------\n")
print "\n------------- Query without Index --------------"
file.write("\n------------- Query without Index --------------\n")
for r = 1; r < (%s + 1); r++ % runs
    print "Run %s of %s \n" % r % runs

    db2 FLUSH PACKAGE CACHE DYNAMIC

    output = python reads.py -r1 -pquery1.sql -q$queries -shotelspec -k6 -a5
    file.write(output)

file.close()

6
你之前的努力看起来如何?这是一个问答网站,而不是免费的代码商店,所以如果你展示出一些解决问题的努力,你更有可能得到帮助。至少上面的部分可以轻松地转换为Python代码(例如echo变成print)。 - Marcelo Cantos
嗨,Marcelo,我明白你的意思,当然我会发布我的努力,因为我已经尝试将bash文件重新创建为Python脚本。我会发布我的Python代码。 - Emil Devantie Brockdorff
2
你的Python代码无法编译这一事实可能至少给了你一个线索。采取最小步骤学习你想要使用的语言可能会有所帮助:http://docs.python.org/tutorial/ - msw
3个回答

38

答案

让我们把它分解成小块,尤其是你错误的部分。 :)


作业

outfile=ReadsAgain.txt

毫不意外地,您需要在字符串周围加上引号。另一方面,您可以在=的周围放置空格以增强可读性。

outfilename = "ReadsAgain.txt"

变量扩展 → str.format(或者,% 操作符)

python reads.py <snip/> -q$queries <snip/>

所以你已经知道如何进行重定向,但是如何进行变量扩展呢?你可以使用format方法(v2.6+):

command = "python reads.py -r1 -pquery1.sql -q{0} -shotelspec -k6 -a5".format(queries)

你也可以使用%运算符

#since queries is a number, use %d as a placeholder
command = "python reads.py -r1 -pquery1.sql -q%d -shotelspec -k6 -a5" % queries

C-style loop → 面向对象风格的循环

for ((r = 1; r < ($runs + 1); r++)) do done
Python中的循环与C语言迭代不同。在Python中,你会迭代可迭代对象,例如列表。在此例中,您要做某件事情“runs”次,所以您需要这样做:
for r in range(runs):
  #loop body here

range(runs)等同于[0,1,...,runs-1],是一个由5个整数元素构成的列表,你将重复执行runs次循环体。在每个循环中,r被赋值为列表中的下一个元素。这与你在Bash中所做的完全相同。

如果你感觉有冒险精神,可以使用xrange。它完全等效,但使用了更高级的语言特性(因此更难以用通俗易懂的语言解释),但消耗的资源更少。


输出重定向 → subprocess模块

如果您想要执行程序并获取其输出,这是一个比较困难的部分。谷歌搜索可以帮助您! 显然,排名第一的是stackoverflow上的一个问题:这个问题。您可以使用一个简单的函数来隐藏所有复杂性:

import subprocess, shlex
def get_output_of(command):
  args = shlex.split(command)
  return subprocess.Popen(args,
                          stdout=subprocess.PIPE).communicate()[0]
  # this only returns stdout

所以:

python reads.py -r1 -pquery1.sql -q$queries -shotelspec -k6 -a5 >> $outfile

变成:

command = "python reads.py -r1 -pquery1.sql -q%s -shotelspec -k6 -a5" % queries
read_result = get_output_of(command)

不要过度使用subprocess,Python已经自带了相关功能

如果需要,你可以用以下代码来获取与date命令相同的输出:

import time
time_now = time.strftime("%c", time.localtime()) # Sat May 15 15:42:47 2010

(请注意缺少时区信息。如果这对您很重要,那么这应该是另一个问题的主题。)


你的程序应该是这样的

最终结果应该看起来像这样:

import subprocess, shlex, time
def get_output_of(command):
  #... body of get_output_of
#... more functions ...
if __name__ = "__main__":
  #only execute the following if you are calling this .py file directly,
  #and not, say, importing it
  #... initialization ...
  with file("outputfile.txt", "a") as output_file: #alternative way to open files, v2.5+
    #... write date and other stuff ...
    for r in range(runs):
      #... loop body here ...

附言

与相对简单和短的Bash脚本相比,这肯定看起来很糟糕,对吧?Python不是一种专门的语言:它旨在合理地完成所有任务,但不是直接为运行程序和获取输出而构建的。

尽管如此,你通常不会用Bash编写数据库引擎,对吧?这是不同工具针对不同工作的情况。除非你计划进行某些使用该语言编写非微不足道的更改,否则[Ba]sh绝对是正确的选择。


1
我三个小时前开始写这个,当我几乎完成时,我突然失去了意识。 - badp
3
对于那种慷慨的精神、努力工作和详细解释,我点个赞。尽管原帖作者没有花费任何心思去学习Python或StackOverflow(我也有同样的过错),但这些都被忽略了。 - msw

11

把你的程序移植应该相当简单。唯一棘手的部分将是运行db2命令和(也许)重构reads.py,使其能够被调用为库函数。

基本思路是相同的:

  • 设置本地变量相同。
  • print替换echo
  • for r in range(runs):替换循环。
  • 使用datetime模块获取日期。
  • 文件对象模块替换写入文件。
  • subprocess模块替换对db2的调用。
  • 您需要import reads.py作为库使用(或者可以使用subprocess)。

但是,正如Marcelo所说,如果您想获得更多帮助,最好自己做出一些努力提出具体问题。


2
尽管我赞成使用Python而不是bash编写代码,但如果有人只是想将其转换为Python以便在Windows上运行,请记住您可以在Windows上安装bash并直接运行它。Cygwin.com提供了许多Unix命令的完整实现。

我的第一个想法是在Cygwin中运行bash,但问题是Cygwin和DB2之间存在通信问题,而bash文件的主要原因之一是运行不同的DB2查询,以便我可以测试不同的索引以优化性能。但如果有解决方案的话,在Cygwin中执行会是最好的解决方案。 - Emil Devantie Brockdorff
抱歉,为什么Cygwin Bash会有问题?您可以从Cygwin Bash shell调用非Cygwin可执行文件,只需要知道Cygwin路径,即使如此,我知道Cygwin也可以进行一些Windows到Cygwin路径转换。例如,您可以调用/cygdrive/c/programfiles/db2,当然前提是您有一个非Cygwin的db2实现要使用。此外,您甚至可以调用Windows Python解释器来运行脚本,而不是列出的那个(但我在Cygwin环境中使用Windows可执行文件运行终端Python脚本时遇到了问题)。 - iondiode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接