Reputation: 6337
I'm just learning Python. One thing I hope to use Python for is Linux shell scripting. I've been studying some examples and practicing by converting my bash scripts to Python.
I just spent a few hours converting one of my bash scripts to Python and I was very disappointed with my resulting code. It was much more verbose and syntactically cluttered. It was certainly not concise and tight like the bash script I started with.
Then I stumbled across this (unrelated) Ruby script. Wow. It seems to give direct access to the shell, unlike Python which has a layer or two between the language and the shell.
#! /usr/bin/ruby
MAX_TIME_SINCE_START = 1800
begin
curr_time = Time.new.to_i
kslideshow_processes_list = `pgrep kslideshow.kss`.split("\n")
kslideshow_processes_list.each { |kslideshow_process|
kslideshow_process.strip!
ps_result = `ps -p #{kslideshow_process} -o lstart`
process_start_date = `ps -p #{kslideshow_process} -o
lstart`.split("\n")[1].strip
get_date_command = "date -d \"#{process_start_date}\" +\"%s\""
kslideshow_start_time = `#{get_date_command}`.to_i
time_since_started = curr_time - kslideshow_start_time
if time_since_started MAX_TIME_SINCE_START
system( "kill #{kslideshow_process}" )
end
}
sleep MAX_TIME_SINCE_START
end while true
This is the kind of code I was hoping would result from my switch from bash script to Python. Is it possible in Python to write shell scripts so cleanly?
It would be very educational for me to see the above code converted to Python by someone who knows what they are doing.
I don't intend to start a Ruby vs. Python discussion. I simply want to see how cleanly the above task can be implemented in Python by someone who knows more Python than I do. Is that a fair question for this site? Thanks
Upvotes: 0
Views: 159
Reputation: 76642
You can IMO do this at least as elegant as in Ruby by using the plumbum
package. There are ways to optimize away system calls (e.g. using dateutils
to convert from a date format, or using psutils
), but that would no longer be a comparison of calling system utilities (I hope I got the logic from the Ruby example correct):
from time import time, sleep
from plumbum.cmd import pgrep, ps, date, kill
MAX_TIME_SINCE_START = 5 # 1800
while True:
curr_time = time()
for kslideshow_process in pgrep("gimp").split():
print kslideshow_process
process_start_date = ps("-p", kslideshow_process, "-o", "lstart"
).split("\n")[1].strip()
kslideshow_start_time = int(date("-d", process_start_date, '+%s'))
print kslideshow_start_time
time_since_started = curr_time - kslideshow_start_time
if time_since_started > MAX_TIME_SINCE_START:
kill([kslideshow_process])
sleep(MAX_TIME_SINCE_START)
You can import any commandline program using from plumbum.cmd import ...
and it is automatically available as a function that takes the commandline arguments as parameters.
You can also make chains of commands:
chain = ls["-a"] | grep["-v", "\\.py"] | wc["-l"]
result = chain()
so there is far less often need for intermediate variables to carry results from one subshell to another.
Upvotes: 2
Reputation: 1582
Barring the bad ideas and ways you could poke your own eye out.. an example of the more efficient way to open a another process in python is as follows...
process = subprocess.Popen([MyCommand, parameter1, "parameter 2"], shell=False, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stdin=subprocess.PIPE)
stdout,stderr = process.communicate()
return_code = process.poll()
Doing things with popen is a little bit more overhead than some other languages, but it offers a lot of versatility that no other scripting language I know of offers like getting output from many many processes live.
Upvotes: 1