Answer

Let's break it down into pieces. Especially the pieces you got wrong. :)


Assignment

outfile=ReadsAgain.txt

It should come to little surprise that you need to put quotes around strings. On the other hand, you have the luxury of putting spaces around the = for readability.

outfilename = "ReadsAgain.txt"

Variable expansion → str.format (or, the % operation)

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

So you know how to do the redirection already, but how do you do the variable expansion? You can use the format method (v2.6+):

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

You can alternatively use 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-style loop → Object-oriented-style loop

for ((r = 1; r < ($runs + 1); r++)) do done

Looping in Python is different from C-style iteration. What happens in Python is you iterate over an iterable object, like for example a list. Here, you are trying to do something runs times, so you would do this:

for r in range(runs):
  #loop body here

range(runs) is equivalent to [0,1,...,runs-1], a list of runs = 5 integer elements. So you'll be repeating the body runs times. At every cicle, r is assigned the next item of the list. This is thus completely equivalent to what you are doing in Bash.

If you're feeling daring, use xrange instead. It's completely equivalent but uses more advanced language features (so it is harder to explain in layman's terms) but consumes less resources.


Output redirection → the subprocess module

The "tougher" part, if you will: executing a program and getting its output. Google to the rescue! Obviously, the top hit is a stackoverflow question: this one. You can hide all the complexity behind it with a simple function:

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

So:

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

becomes:

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

Don't over-subprocess, batteries are included

Optionally, consider that you can get pretty much the same output of date with the following:

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

(Note the absence of the time zone information. This should be the subject of another question, if it is important to you.)


How your program should look like

The final result should then look like this:

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 ...

Post scriptum

That must look pretty horrible when compared to the relatively simple and short Bash script, right? Python is not a specialized language: it aims to do everything reasonably well, but isn't built directly for running programs and getting the output of those.

Still, you wouldn't normally write a database engine in Bash, right? It's different tools for different jobs. Here, unless you're planning to make some changes that would be non-trivial to write with that language, [Ba]sh was definitely the right choice.

Answer from badp on Stack Overflow
Top answer
1 of 3
38

Answer

Let's break it down into pieces. Especially the pieces you got wrong. :)


Assignment

outfile=ReadsAgain.txt

It should come to little surprise that you need to put quotes around strings. On the other hand, you have the luxury of putting spaces around the = for readability.

outfilename = "ReadsAgain.txt"

Variable expansion → str.format (or, the % operation)

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

So you know how to do the redirection already, but how do you do the variable expansion? You can use the format method (v2.6+):

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

You can alternatively use 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-style loop → Object-oriented-style loop

for ((r = 1; r < ($runs + 1); r++)) do done

Looping in Python is different from C-style iteration. What happens in Python is you iterate over an iterable object, like for example a list. Here, you are trying to do something runs times, so you would do this:

for r in range(runs):
  #loop body here

range(runs) is equivalent to [0,1,...,runs-1], a list of runs = 5 integer elements. So you'll be repeating the body runs times. At every cicle, r is assigned the next item of the list. This is thus completely equivalent to what you are doing in Bash.

If you're feeling daring, use xrange instead. It's completely equivalent but uses more advanced language features (so it is harder to explain in layman's terms) but consumes less resources.


Output redirection → the subprocess module

The "tougher" part, if you will: executing a program and getting its output. Google to the rescue! Obviously, the top hit is a stackoverflow question: this one. You can hide all the complexity behind it with a simple function:

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

So:

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

becomes:

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

Don't over-subprocess, batteries are included

Optionally, consider that you can get pretty much the same output of date with the following:

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

(Note the absence of the time zone information. This should be the subject of another question, if it is important to you.)


How your program should look like

The final result should then look like this:

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 ...

Post scriptum

That must look pretty horrible when compared to the relatively simple and short Bash script, right? Python is not a specialized language: it aims to do everything reasonably well, but isn't built directly for running programs and getting the output of those.

Still, you wouldn't normally write a database engine in Bash, right? It's different tools for different jobs. Here, unless you're planning to make some changes that would be non-trivial to write with that language, [Ba]sh was definitely the right choice.

2 of 3
11

It should be fairly simple to port your program. The only tricky part will be running the db2 command and (maybe) refactoring reads.py so that it can be called as a library function.

The basic idea is the same:

  • Setting local variables is the same.
  • Replace echo with print.
  • Replace your loop with for r in range(runs):.
  • Get the date with the datetime module.
  • Replace write to file with the file objects module.
  • Replace the call to db2 with the subprocess module.
  • You'll need to import reads.py to use as a library (or you can use subprocess).

But, as Marcelo says, if you want more help- you're best off putting in some effort of your own to ask direct questions.

🌐
grep Flags
zwischenzugs.com › 2016 › 08 › 29 › bash-to-python-converter
Bash to Python Converter – zwischenzugs.com
August 29, 2016 - bash2py does some safe conversion and wrapping of the bash script into some methods such as ‘Make’, ‘Array’ et al that we can get rid of with a little work.
🌐
Linux Questions
linuxquestions.org › questions › linux-software-2 › need-help-converting-bash-script-to-python-4175605267
Need help converting BASH script to Python
Ive been tasked to convert a bash script to python. So far, the only way I know how to do that is to wrap every statement in the bash script with a
🌐
CodingFleet
codingfleet.com › code-converter › bash › python
Bash to Python Converter - CodingFleet
Convert your Bash Code to Python. This exceptional AI-powered tool converts your Bash code into Python code easily, eliminating the need for manual re-coding. Save your precious time and unlock cross-platform development like never before with our converter tool.
🌐
Medium
medium.com › capital-one-tech › bashing-the-bash-replacing-shell-scripts-with-python-d8d201bc0989
Bashing the Bash — Replacing Shell Scripts with Python | by Steven F. Lott | Capital One Tech | Medium
February 21, 2020 - A line of shell code is parsed as words based on whitespace and quotes. Quoted strings are treated as a single word. The shell provides two kinds of quotes to provide some control over the process. For Python, I’ve parsed the command into a list of words at design time.
🌐
GitHub
github.com › syuanca › bash2python
GitHub - syuanca/bash2python: A tool that converts a bash script to python script
A tool that converts a bash script to python script - syuanca/bash2python
Starred by 22 users
Forked by 11 users
Languages   Python 56.7% | Shell 43.3% | Python 56.7% | Shell 43.3%
🌐
bootvar
bootvar.com › how-to-convert-shell-script-to-python
How I converted my bash scripts into Python? - bootvar
October 20, 2022 - Below are some useful libraries for above functionalities and in general for converting bash to Python. argparse/click - for parsing arguments passed to a script (in detail) you can parse command line arguments which needs to be passed to the script.
Find elsewhere
Top answer
1 of 2
5

You can use the subprocess module :

#!/usr/bin/env python2
import subprocess
command_1 = 'ps -eo pid,ppid,user,rss,comm --sort=rss'.split()
command_2 = 'tail -10'.split()
first = subprocess.Popen(command_1, stdout=subprocess.PIPE)
subprocess.call(command_2, stdin=first.stdout)
  • command_1 is the command on the left of the pipe, split on spaces to make a list which is required by subprocess.Popen class

  • command_2 is the command on the left of the pipe split similarly to command_1

  • first is an object of the subprocess.Popen class, subprocess.Popen executes the command_1 and send its STDOUT to PIPE so that we can use it as an input to command_2

  • subprocess.call will execute the command_2 with its STDIN coming from the STDOUT of first

For ps -C kswapd0 -C kswapd1 -C kswapd2 -C kswapd3 -C kswapd4 -o pid,ppid,stime,etime,time,pcpu,args command you can do :

#!/usr/bin/env python2
import subprocess
command = 'ps -C kswapd0 -C kswapd1 -C kswapd2 -C kswapd3 -C kswapd4  -o pid,ppid,stime,etime,time,pcpu,args'.split()
subprocess.call(command)

Read the official documentation on subprocess to get more idea.

2 of 2
3

I'd use something like psutil to grab the data programmatically.

That's going to take a little while to learn so the quicker, scrappier alternative is to run the commands through a subshell-style construct from Python.

import commands
exit_code, output = commands.getstatusoutput('ps -eo pid,ppid,user,rss,comm --sort=rss')
print '\n'.join(output.split('\n')[-10:])

I've moved the tail into pure Python there, just for fun.

🌐
GitHub
github.com › clarity20 › bash2py
GitHub - clarity20/bash2py: The only Bash-to-python transpiler you will ever need! https://www.swag.uwaterloo.ca/bash2py/index.html
Welcome to the new home of bash2py, a software tool that translates Bash shell code into Python.
Starred by 38 users
Forked by 17 users
Languages   C 68.7% | HTML 15.9% | Yacc 6.6% | Shell 3.1% | Perl 2.6% | Makefile 2.1% | C 68.7% | HTML 15.9% | Yacc 6.6% | Shell 3.1% | Perl 2.6% | Makefile 2.1%
🌐
freeCodeCamp
freecodecamp.org › news › python-for-system-administration-tutorial
How to Replace Bash with Python as Your Go-To Command Line Language
January 20, 2020 - Before we get into the examples let's just list some handy packages along with their docs. My go to package is the os package. You can use it to list directories, check if files exist, check if symlinks exist, make directories, run system commands, get and set environmental variables, and more. It's great! My second package for running system commands that don't exist as handy python libraries is the subprocess module.
🌐
Python.org
discuss.python.org › python help
Automatically converting (most of?) n bash scripts to Python? - Python Help - Discussions on Python.org
June 21, 2024 - Hello people. I’ve been writing a bunch of scripts, sometimes in bash, sometimes in Python, to automate the mundane parts of my job. My management has decided they don’t want the bash anymore, so I’ve been asked to mov…
🌐
myByways
mybyways.com › blog › migrating-from-bash-shell-scripts-to-python
Migrating from bash shell scripts to Python | myByways
March 11, 2021 - Use Pyhton f-strings, and never go back to print('Hello ' + a + '!')! Available since Python 3.6 December 2016.
🌐
CodeConvert AI
codeconvert.ai › bash-to-python-converter
Online Bash to Python Converter
Type or paste your Bash code in the input box. Click the convert button. The resulting Python code from the conversion will be displayed in the output box.
🌐
ResearchGate
researchgate.net › publication › 295302947_Bash2py_A_bash_to_Python_translator
Bash2py: A bash to Python translator | Request PDF
March 1, 2015 - Bash also suffers from poor performance, memory leakage problems, and limited functionality which make continued dependence on it problematic. At the request of our industrial partner, we therefore developed a source-to-source translator, bash2py, which converts bash scripts into Python.
🌐
GeeksforGeeks
geeksforgeeks.org › how-to-run-bash-script-in-python
How to run bash script in Python? - GeeksforGeeks
September 13, 2022 - Suppose you have written your bash script that needs to be invoked from python code. The two common modules for interacting with the system terminal are os and subprocess module. Let's consider such a simple example, presenting a recommended approach to invoking subprocesses. As an argument, you have to pass the command you want to invoke and its arguments, all wrapped in a list.
Top answer
1 of 2
3
import os

for i in range(1, 50):
    env_var = os.environ[f'{i}nl']
    os.system(f"ssh BF-c{env_var} 'hostname; free -h; uname -a;'")

Python3.6 >

    env_var = os.environ[str(i) + 'nl']
    os.system("ssh BF-c{} 'hostname; free -h; uname -a;'".format(env_var))
2 of 2
2

You can do it using Bash2Py.

Also, you can try using the docker image

Courtesy: Bash to Python

So the below code is actually the complete script for conversion.

#! /usr/bin/env python
from __future__ import print_function

import sys,os

class Bash2Py(object):
  __slots__ = ["val"]
  def __init__(self, value=''):
    self.val = value
  def setValue(self, value=None):
    self.val = value
    return value

def GetVariable(name, local=locals()):
  if name in local:
    return local[name]
  if name in globals():
    return globals()[name]
  return None

def Make(name, local=locals()):
  ret = GetVariable(name, local)
  if ret is None:
    ret = Bash2Py(0)
    globals()[name] = ret
  return ret

def Array(value):
  if isinstance(value, list):
    return value
  if isinstance(value, basestring):
    return value.strip().split(' ')
  return [ value ]

class Expand(object):
  @staticmethod
  def at():
    if (len(sys.argv) < 2):
      return []
    return  sys.argv[1:]
  @staticmethod
  def star(in_quotes):
    if (in_quotes):
      if (len(sys.argv) < 2):
        return ""
      return " ".join(sys.argv[1:])
    return Expand.at()
  @staticmethod

  def hash():
    return  len(sys.argv)-1

if (Expand.hash() < 1 ):
    print("Usage: "+__file__+" file ...")
    exit(1)

print(__file__+" counts the lines of code")

l=Bash2Py(0)

for Make("f").val in Expand.star(0):
    Make("l").setValue(os.popen("wc -l "+str(f.val)+" | sed \"s/^\\([0-9]*\\).*$/\\1/\"").read().rstrip("\n"))
    print(str(f.val)+": "+str(l.val))

The guts of the code is in the for loop at the bottom.

bash2py does some safe conversion and wrapping of the bash script into some methods such as ‘Make’, ‘Array’ et al that we can get rid of with a little work.

By replacing:

  • Bash2Py(0) with 0
  • Make(“f”).val with f and Make(“l”) with l etc
  • f.val with f and l.val with l etc
🌐
Osgeo
grasswiki.osgeo.org › wiki › Converting_Bash_scripts_to_Python
Converting Bash scripts to Python - GRASS-Wiki
February 2, 2013 - This page contains some notes for the users who are converting their Bash script to Python. 1 User break · 2 Discard warning/error messages · In Bash: # what to do in case of user break: exitprocedure() { g.remove rast=$TMP1 > /dev/null } # shell check for user break (signal list: trap -l) trap "exitprocedure" 2 3 15 · In Python: import sys import atexit import grass.script as grass def cleanup(): grass.run_command('g.remove', rast = tmp1) def main(): ...
🌐
Medium
medium.com › zwischenzugs › bash-to-python-converter-c58580f26f6c
Bash to Python Converter | by Ian Miell | zwischenzugs | Medium
October 9, 2016 - bash2py does some safe conversion and wrapping of the bash script into some methods such as 'Make', 'Array' et al that we can get rid of with a little work.