HowTo send emails reliably in a Python multi-threading application?
Josiah Carlson
jcarlson at nospam.uci.edu
Sat Feb 21 12:42:49 EST 2004
> 1) How can one send mails reliable in a multi-threaded Python application?
> Should the email package be used? Should smtplib be used or is it better to
> call "sendmail" or "mail" directly? Should popen2 or os.system() be
> preferred?
I don't think this matters one way or another. It may be convenient to
use smtplib, if only because it wouldn't rely on sendmail or mail. The
problem with smtplib is that if you get rid of threads (which I suggest
later), smtplib could stall your program.
> 2) How to call an external tool (or many of them) and connect them via pipes
> with each other and with the Python script in a multithreaded application? I
> read the discussion http://www.python.org/doc/current/lib/
> popen2-flow-control.html several times now and think I followed the
> suggestions given there, but it seems still to cause trouble for me.
Connect them the same way you would in a shell (as you seem to be doing
already), with commands like:
command1 | command2 | command3
For getting the output from command3, I've always been a big fan of:
procs['unique_done'] = os.popen('command1 | command2 | command3 |'
' special unique_output unique_done')
Where special is a command that passes-though all information received
from command3, writes it to unique_output, and when done, creates a file
called unique_done, but doesn't write anything to stdout.
However often you want to, you can check for the existance of
unique_done (as many of them as you want) and execute the following:
toss = procs['unique_done'].read()
procs['unique_done'].close()
del procs['unique_done']
fil = open('unique_output', 'rb')
output = fil.read()
fil.close()
os.remove('unique_output')
os.remove('unique_done')
Personally, I would toss the multi-threaded portion and stick with
asynchronous IO. You don't mention how you are handling new information
coming into the system, whether this is by sockets or polling for files,
but basically everything can be wrapped up in an async loop:
while not quit:
asyncore.poll(0) #handles socket IO
poll_and_handle_done() #would check for all done
#outputs, and process them as above
By not using threads, you should find your software moves a few percent
faster when loaded heavily.
> - - very, very seldom (1 out of 5000 received faxes), one user of me saw the
> following - at least with Python 2.2.2; I have no feedback about newer
> versions yet:
> File "/usr/lib/python2.2/site-packages/cs_helpers.py", line 233, in
> sendMIMEMail
> sendmail.tochild.write(msg.as_string())
> File "/var/tmp/python-2.2.2-build//usr/lib/python2.2/email/Message.py", line
> 107, in as_string
> File "/var/tmp/python-2.2.2-build//usr/lib/python2.2/email/Generator.py", line
> 100, in flatten
> File "/var/tmp/python-2.2.2-build//usr/lib/python2.2/email/Generator.py", line
> 135, in _write
> File "/var/tmp/python-2.2.2-build//usr/lib/python2.2/email/Generator.py", line
> 167, in _write_headers
> File "/var/tmp/python-2.2.2-build//usr/lib/python2.2/email/Generator.py", line
> 191, in _split_header
> File "/var/tmp/python-2.2.2-build//usr/lib/python2.2/email/Generator.py", line
> 41, in _is8bitstring
> File "/var/tmp/python-2.2.2-build//usr/lib/python2.2/encodings/__init__.py",
> line 43, in search_function
> AttributeError: 'NoneType' object has no attribute 'get'
I don't know about this one, but it looks like somewhere your software
is passing a None when it should be passing a dictionary.
Good luck to you,
- Josiah
More information about the Python-list
mailing list