【问题标题】:Converting a bash script to python (small script)将 bash 脚本转换为 python(小脚本)
【发布时间】:2011-02-19 20:30:39
【问题描述】:

我有一个用于 Linux 环境的 bash 脚本,但现在我必须在 Windows 平台上使用它,并且想将 bash 脚本转换为我可以运行的 python 脚本。

bash 脚本相当简单(我认为),我尝试通过 google 对其进行转换,但无法成功转换。

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 脚本,或者至少给我一些提示和方向,那真的会帮助我。

真诚的

梅斯蒂卡

按请求添加:

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

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

【问题讨论】:

  • 您之前的努力是什么样的?这是一个问答网站,而不是免费的代码商店,所以如果您自己努力解决问题,您更有可能获得帮助。至少上面的一些东西可以简单地转换为 Python(echo => print 等)。
  • 嗨,Marcelo,我明白你在说什么,当然我会发布我自己的努力,因为我试图在 python 脚本中重新创建 bash 文件。我将发布我的 python 代码
  • 您的 Python 代码无法编译这一事实可能至少会给您一个线索。采取最少的步骤来学习您想要使用的语言可能会有所帮助:docs.python.org/tutorial

标签: python bash


【解决方案1】:

回答

让我们把它分解成碎片。尤其是你弄错的部分。 :)


作业

outfile=ReadsAgain.txt

您需要在字符串周围加上引号应该不足为奇。另一方面,您可以在 = 周围放置空格以提高可读性。

outfilename = "ReadsAgain.txt"

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

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

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

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

您也可以使用the % operator:

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

C 风格循环 → Object-oriented-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]runs = 5 整数元素的列表。所以你会重复身体runs 次。在每个 cicle 中,r 被分配到列表的下一项。因此,这完全等同于您在 Bash 中所做的。

如果您觉得大胆,请改用xrange。它完全等效,但使用了更高级的语言功能(因此用外行的话很难解释)但消耗的资源更少。


输出重定向→the subprocess module

“更难”的部分,如果你愿意的话:执行一个程序并获得它的输出。 Google to the rescue! 显然,最热门的是一个stackoverflow 问题:this one。你可以用一个简单的函数来隐藏它背后的所有复杂性:

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,包括电池

或者,考虑到您可以获得与 date 几乎相同的输出:

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

(请注意缺少时区信息。如果对您很重要,这应该是another question 的主题。)


你的程序应该是什么样子的

最后的结果应该是这样的:

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 表示慷慨的精神、辛勤的工作和仔细的解释,忽略了 OP 没有花丝毫努力学习 Python 或 StackOverflow 的事实(我也犯了同样的罪) .
【解决方案2】:

移植您的程序应该相当简单。唯一棘手的部分是运行 db2 命令和(可能)重构 reads.py 以便可以将其作为库函数调用。

基本思路是一样的:

  • 设置局部变量是一样的。
  • echo 替换为print
  • 将循环替换为 for r in range(runs):
  • 使用datetime 模块获取date
  • 将写入文件替换为 file objects 模块。
  • 将对db2 的调用替换为subprocess 模块。
  • 您需要import reads.py 才能用作库(或者您可以使用子进程)。

但是,正如 Marcelo 所说,如果您需要更多帮助 - 您最好自己努力直接提出问题。

【讨论】:

    【解决方案3】:

    尽管我赞成用 Python 而不是 bash 编写,但如果将其转换为 Python 的唯一原因是您可以在 Windows 上运行它,请记住您可以在 Windows 上安装 bash 并运行它照原样。 Cygwin.com 有很多 Unix 命令的完整实现。

    【讨论】:

    • 我首先想到的是在我的 cygwin 中运行 bash,但问题是 Cybwin 和 DB2 无法一起交谈,而 bash 文件的主要原因之一是在 DB2 中运行不同的查询,所以我可以测试不同的索引来优化性能。但如果有解决方案,这将是在 Cygwin 中执行此操作的最佳解决方案。
    • 抱歉,为什么 cygwin bash 有问题?您可以从 cygwin bash shell 调用非 cygwin 可执行文件,您只需要知道 cygwin 路径,即使这样我也知道 cygwin 可以做一些窗口到 cygwin 路径的转换。例如,您可以调用 /cygdrive/c/programfiles/db2 ,当然假设您有一个要使用的非 cygwin db2 实现。此外,您甚至可以调用 windows python 解释器来运行您的脚本,而不是列出的脚本(但我在使用 cygwin env 中的 windows 可执行文件运行终端 python 脚本时遇到了问题)
    猜你喜欢
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 2015-10-16
    • 2020-01-08
    • 2021-04-15
    相关资源
    最近更新 更多