Newbie: executing a system command from my Python app

D

Dan M

I'm writing a Python replacement for a particularly ugly shell script. we
are running mimedefang on our mail server, moving spam and virus messages
to a quarantine directory. This little python script successfully chdir's
to the quarantine directory, identifies all of the quarantine
subdirectories for yesterday's messages, and stuffs them into a tar file
in an archive directory. I then want to delete for successfully tarred
files and the subdirs they live in.

By way of further explanation, quarantined messages get broken into files
named ENTIRE_MESSAGE, HEADERS, RECIPIENTS, SENDER, and SENDMAIL-QID, and
get stored in subdirectories named qdir-YYYY-MM-DD-hh.mm.ss-nnn, where
Y-M-D is the date received, hms is time received, and nnn is to allow for
up to 10 messages to quarantined any given second.

I know I can do this by descending into the directories I've identified
and unlink()ing each of the files, but I'd like to take a shortcut like:
"retval = os.system('rm -rf /var/spool/MD-Quarantine/qdir-%s*' %
(dateYest))" and indeed code written that executes without any errors.
Unfortunately it also leaves a bunch of qdir-2005-12-11-* files sitting
around when I run it on 12-11.

Have I overlooked some basic operation of the os.system() call? From all
I've seen in the online docs and O'Reilly's "Programming Python" it looks
like it should be working.

Here's my complete script:
#!/usr/local/bin/python

import glob, os, tarfile, time, datetime
DATE_FMT = "%Y-%m-%d"
filelist = []

yest = datetime.date.today() + datetime.timedelta(days = -1)
dateYest = yest.strftime(DATE_FMT)

os.chdir("/var/spool/MD-Quarantine")

try:
tar = tarfile.open("/usr/local/archives/MD-Q/%s.tar.gz" % (dateYest), "w:gz")
for file in glob.glob("qdir-%s*" % (dateYest)):
tar.add(file)
filelist.append(file)
tar.close()
except TarError:
print "The quarantine file archiving program threw a TarError exception" exit()

cmd = "rm -rf /var/spool/MD_Quarantine/qdir-%s*" % (dateYest)
print "About to execute ", cmd
retval = os.system(cmd)
 
D

Dan M

I'm writing a Python replacement for a particularly ugly shell script. we
are running mimedefang on our mail server, moving spam and virus messages
to a quarantine directory. This little python script successfully chdir's
to the quarantine directory, identifies all of the quarantine
subdirectories for yesterday's messages, and stuffs them into a tar file
in an archive directory. I then want to delete for successfully tarred
files and the subdirs they live in.

Never mind - the flaw was in how I was building the command to be executed
by os.system. It's working fine now.
 
J

James Stroud

Dan said:
I'm writing a Python replacement for a particularly ugly shell script. we
are running mimedefang on our mail server, moving spam and virus messages
to a quarantine directory. This little python script successfully chdir's
to the quarantine directory, identifies all of the quarantine
subdirectories for yesterday's messages, and stuffs them into a tar file
in an archive directory. I then want to delete for successfully tarred
files and the subdirs they live in.

By way of further explanation, quarantined messages get broken into files
named ENTIRE_MESSAGE, HEADERS, RECIPIENTS, SENDER, and SENDMAIL-QID, and
get stored in subdirectories named qdir-YYYY-MM-DD-hh.mm.ss-nnn, where
Y-M-D is the date received, hms is time received, and nnn is to allow for
up to 10 messages to quarantined any given second.

I know I can do this by descending into the directories I've identified
and unlink()ing each of the files, but I'd like to take a shortcut like:
"retval = os.system('rm -rf /var/spool/MD-Quarantine/qdir-%s*' %
(dateYest))" and indeed code written that executes without any errors.
Unfortunately it also leaves a bunch of qdir-2005-12-11-* files sitting
around when I run it on 12-11.

Few points points:

1. Generally: I would try to minimize system calls. They make your code less
portable.
2. Look into the "shutil" module for recursive deletion.
3. Use os.path to construct paths. Try to avoid, for example,
"c:\blah\blah" on dos, '/blah/blah' on unix, etc.
4. If you only have one argument, you don't need a tuple for string formatting.
5. "(dateYest)" is not a tuple anyway--the parentheses are superfluous
6. Single item tuples can be created with "(anitem,)" (notice the comma).

James
 
D

Dan M

Few points points:
1. Generally: I would try to minimize system calls. They make your code less
portable.

Excellent point. In this case the app will never live anywhere other than
one specific FreeBSD machine, but I do appreciate the value of the advice
anyway. Therefore...
2. Look into the "shutil" module for recursive deletion.
3. Use os.path
to construct paths. Try to avoid, for example,
"c:\blah\blah" on dos, '/blah/blah' on unix, etc.

Have done so. Thanks for pointing out the shutils module! I keep finding
more and more excellent modules available. Do we have a Python equivalent
to Perl's CPAN?
4. If you only have one argument, you don't need a tuple
for string formatting.
5. "(dateYest)" is not a tuple anyway--the parentheses are
superfluous 6. Single item tuples can be created with "(anitem,)"
(notice the comma).

That helps. I had somehow gotten the mistaken idea that string formatting
always needed a tuple, and overlooked the trailing comma. I've applied
that correction to several of my other Python scripts as well.
 
D

Donn Cave

4. If you only have one argument, you don't need a tuple
for string formatting.
5. "(dateYest)" is not a tuple anyway--the parentheses are
superfluous 6. Single item tuples can be created with "(anitem,)"
(notice the comma).

That helps. I had somehow gotten the mistaken idea that string formatting
always needed a tuple, and overlooked the trailing comma. I've applied
that correction to several of my other Python scripts as well.[/QUOTE]

Doesn't always need a tuple, but does need a tuple if the
parameter to be converted is already a tuple. So the tuple
isn't exactly gratuitous. In fact in a way it makes your code
more polymorphic, which is said to bring good luck.

When you're sure that the expression that appears there on the
right hand side of % is not and will never be a tuple, then
the (a,) one-tuple is unnecessary. If you aren't sure, it _is_
necessary.

Donn Cave, (e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top