6
\$\begingroup\$

I use at to schedule jobs and atq to display the scheduled jobs. But it mildly irritates me in that I have to look up each job individually. I wrote a Python script to display the scheduled job under the scheduled time.

(In my world all the commands will begin 'task')

So instead of

stafflinux$atq
8   Mon Aug 18 09:00:00 2014 a joseph
10  Tue Aug 19 09:00:00 2014 a joseph
15  Thu Aug 21 09:00:00 2014 a joseph
12  Fri Aug 22 09:00:00 2014 a joseph
9   Thu Aug 21 09:00:00 2014 a joseph
14  Sat Aug 30 09:00:00 2014 a joseph
7   Sun Aug 17 09:00:00 2014 a joseph
6   Mon Aug 18 09:00:00 2014 a joseph
11  Sat Aug 30 09:00:00 2014 a joseph
stafflinux$

My script produces

stafflinux$./atscript.py 
8  Mon Aug 18 09:00:00 2014 a joseph
task "buy a four-way plug adapter" 
task "see guy about meeting" 
-----------------------------------------
10  Tue Aug 19 09:00:00 2014 a joseph
task "bring back personal effects from office" 
-----------------------------------------
15  Thu Aug 21 09:00:00 2014 a joseph
task "book tickets for next week"
-----------------------------------------

I'm looking for any feedback - particularly in terms of 'pythonic' style and any and all tricks I may have missed:

#!/usr/bin/python
import os
os.system("atq > attemp.txt") 
file = open("attemp.txt")
line = file.readline()
while line: 
    number =line[:2]
    print line.strip()
    os.system("at -c "+ number+ "| grep task")
    line=file.readline()
    print '-----------------------------------------'
print line
os.system("rm attemp.txt")
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Your script creates a temporary file unnecessarily, uses os.system which is not recommended, and other messy things. Consider this alternative:

#!/usr/bin/env python

import subprocess
import re

re_job_number = re.compile(r'\d+')

for atq_line in subprocess.Popen(['atq'], stdout=subprocess.PIPE).stdout:
    job_number = re_job_number.search(atq_line).group()
    print atq_line.strip()
    for at_line in subprocess.Popen(['at', '-c', job_number], stdout=subprocess.PIPE).stdout:
        if at_line.startswith('task '):
            print at_line.strip()
    print '-' * 40

Advantages:

  • No need for a temporary file to save the atq output, you can process it directly
  • For running shell commands, subprocess is the recommended way, os.system is discouraged
  • No need for a grep process, you can handle the output filtering of at -c in Python itself

Also, writing the first line this way makes the script more portable:

#!/usr/bin/env python

If you write as #!/usr/bin/python then you are effectively hard-coding the Python path, and it might not be the same in all systems.

Finally, I recommend writing print(something) instead of print something, to keep your script ready for migrating to Python 3 someday.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Hard-coding #!/usr/bin/python is not necessarily a bad idea — it's a judgement call. \$\endgroup\$ Aug 15, 2014 at 18:20
2
\$\begingroup\$

You should segment your code in a way that makes it more readable.

#!/usr/bin/python
import os

os.system("atq > attemp.txt") 
file = open("attemp.txt")
line = file.readline()

while line: 
    number =line[:2]
    print line.strip()
    os.system("at -c "+ number+ "| grep task")
    line=file.readline()
    print '-----------------------------------------'

print line
os.system("rm attemp.txt")

Additionally, you should use the with context manager, which takes care of file closing and error handling for you. Also, you should avoid using strings all over the place and store the filename in a variable. You should also avoid setting unnecessary variables (like number). Additionally, use Python's string multiplication abilities ('-' * 40 will print 40 '-'). Your script would now look like:

#!/usr/bin/python
import os

filename = 'attemp.txt'
os.system("atq > " + filename)

with open(filename, 'r') as handle:
    for line in handle:
        print line.strip()
        os.system('at -c ' + line[:2] + ' | grep task')
        print ('-' * 40) + "\n" + line

os.system("rm " + filename)

This is untested code, but it should work the same as your original code.

\$\endgroup\$
1
  • \$\begingroup\$ Do note that it will remove your attemp.txt, which I'm not sure if its truly intended to do so (I'd honestly keep the txt file just in case I had to re-run it) \$\endgroup\$
    – jsanc623
    Aug 15, 2014 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.