Discussion:
[python-win32] Dispatch error 'CoInitialize has not been called'
Bob Gailer
2006-12-29 00:20:16 UTC
Permalink
I'm running this under my Apache2triad mod_python installation.
Yesterday it was working. Today it is not.
In the Apache config mptest.py is defined as the request handler. When
called via an HTTP request I get the following:

Traceback (most recent call last):

File "H:\Python24\Lib\site-packages\mod_python\apache.py", line 299,
in HandlerDispatch
result = object(req)

File "H:/apache2triad/htdocs/output/mptest.py", line 45, in handler
if actHandler: actHandler(req, parameters)

File "H:/apache2triad/htdocs/output/mptest.py", line 52, in search
connect()

File "H:/apache2triad/htdocs/output/mptest.py", line 26, in connect
conn = win32com.client.Dispatch("ADODB.Connection")

File "H:\Python24\lib\site-packages\win32com\client\__init__.py", line
95, in Dispatch
dispatch, userName =
dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)

File "H:\Python24\lib\site-packages\win32com\client\dynamic.py", line
98, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)

File "H:\Python24\lib\site-packages\win32com\client\dynamic.py", line
78, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx,
pythoncom.IID_IDispatch)

com_error: (-2147221008, 'CoInitialize has not been called.', None, None)

Trying the same thing in the PythonWin interactive window - it works
just fine.
--
Bob Gailer
510-978-4454
Roger Upole
2006-12-29 01:34:51 UTC
Permalink
Post by Bob Gailer
I'm running this under my Apache2triad mod_python installation.
Yesterday it was working. Today it is not.
In the Apache config mptest.py is defined as the request handler. When
File "H:\Python24\Lib\site-packages\mod_python\apache.py", line 299,
in HandlerDispatch
result = object(req)
File "H:/apache2triad/htdocs/output/mptest.py", line 45, in handler
if actHandler: actHandler(req, parameters)
File "H:/apache2triad/htdocs/output/mptest.py", line 52, in search
connect()
File "H:/apache2triad/htdocs/output/mptest.py", line 26, in connect
conn = win32com.client.Dispatch("ADODB.Connection")
File "H:\Python24\lib\site-packages\win32com\client\__init__.py", line
95, in Dispatch
dispatch, userName =
dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "H:\Python24\lib\site-packages\win32com\client\dynamic.py", line
98, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "H:\Python24\lib\site-packages\win32com\client\dynamic.py", line
78, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx,
pythoncom.IID_IDispatch)
com_error: (-2147221008, 'CoInitialize has not been called.', None, None)
Trying the same thing in the PythonWin interactive window - it works
just fine.
If it's running in a thread, you need to call pythoncom.CoInitialize yourself.

Roger
Bob Gailer
2006-12-29 04:47:57 UTC
Permalink
Post by Roger Upole
Post by Bob Gailer
I'm running this under my Apache2triad mod_python installation.
Yesterday it was working. Today it is not.
In the Apache config mptest.py is defined as the request handler. When
File "H:\Python24\Lib\site-packages\mod_python\apache.py", line 299,
in HandlerDispatch
result = object(req)
File "H:/apache2triad/htdocs/output/mptest.py", line 45, in handler
if actHandler: actHandler(req, parameters)
File "H:/apache2triad/htdocs/output/mptest.py", line 52, in search
connect()
File "H:/apache2triad/htdocs/output/mptest.py", line 26, in connect
conn = win32com.client.Dispatch("ADODB.Connection")
File "H:\Python24\lib\site-packages\win32com\client\__init__.py", line
95, in Dispatch
dispatch, userName =
dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "H:\Python24\lib\site-packages\win32com\client\dynamic.py", line
98, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "H:\Python24\lib\site-packages\win32com\client\dynamic.py", line
78, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx,
pythoncom.IID_IDispatch)
com_error: (-2147221008, 'CoInitialize has not been called.', None, None)
Trying the same thing in the PythonWin interactive window - it works
just fine.
If it's running in a thread, you need to call pythoncom.CoInitialize yourself.
OK. I don't know whether its running in a thread. I made no changes that
I'm aware of that would cause the change in behavior. I will add the
call to pythoncom.CoInitialize. I am not familiar with this method.
.... time passes ....
OK I added it and now it works. Thanks.
--
Bob Gailer
510-978-4454
Tim Golden
2006-12-29 09:44:52 UTC
Permalink
[Bob Gailer]
Post by Bob Gailer
OK. I don't know whether its running in a thread. I made no
changes that I'm aware of that would cause the change in
behavior. I will add the call to pythoncom.CoInitialize. I am
not familiar with this method.
This is one of those gotcha's of Win32 COM programming;
you can be happily using some code which runs fine. You
then drop it into a [web server / service / scheduled job]
and lo! you're now running in a thread.

I'm not sure (and perhaps someone can advise) whether there's
any harm in *always* calling CoInitialize!

TJG


Tim Golden
Senior Analyst Programmer
--------------------------------------------------------
Viacom Outdoor Ltd, Camden Wharf, 28 Jamestown Road, London, NW1 7BY T: 020 7482 3000 F: 020 7267 4944
Email: ***@viacom-outdoor.co.uk www.viacom-outdoor.co.uk

The contents of this e-mail are confidential to the ordinary user of the e-mail address to which it was addressed, and may also be privileged. If you are not the addressee of this e-mail you may not copy, forward, disclose or otherwise use it or any part of it in any form whatsoever. If you have received this e-mail in error, please e-mail the sender by replying to this message. Viacom Outdoor Ltd reserves the right to monitor e-mail communications from external/internal sources for the purposes of ensuring correct and appropriate use of Viacom Outdoor facilities.

________________________________________________________________________
This e-mail has been scanned for all viruses by Star. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________
Bob Gailer
2006-12-29 19:29:27 UTC
Permalink
Post by Tim Golden
[Bob Gailer]
Post by Bob Gailer
OK. I don't know whether its running in a thread. I made no
changes that I'm aware of that would cause the change in
behavior. I will add the call to pythoncom.CoInitialize. I am
not familiar with this method.
This is one of those gotcha's of Win32 COM programming;
you can be happily using some code which runs fine. You
then drop it into a [web server / service / scheduled job]
and lo! you're now running in a thread.
Yeah, but when I said it was working, it was working in the server!
Wednesday AM just fine. Wednesday afternoon suddenly not working fine. I
swear I didn't change anything!

Is there some way my program can introspect? to see if it is in a thread?
Post by Tim Golden
I'm not sure (and perhaps someone can advise) whether there's
any harm in *always* calling CoInitialize!
--
Bob Gailer
510-978-4454
Tim Golden
2006-12-29 20:17:08 UTC
Permalink
Post by Bob Gailer
Post by Tim Golden
[Bob Gailer]
Yeah, but when I said it was working, it was working in the server!
Wednesday AM just fine. Wednesday afternoon suddenly not working fine. I
swear I didn't change anything!
Is there some way my program can introspect? to see if it is in a thread?
It's a bit clunky, but I think you can do this:

<code>
import threading
import pythoncom

if threading.currentThread ().getName () <> 'MainThread':
pythoncom.CoInitialize ()

</code>

TJG
Bob Gailer
2006-12-29 22:00:29 UTC
Permalink
Post by Tim Golden
Post by Bob Gailer
Post by Tim Golden
[Bob Gailer]
Yeah, but when I said it was working, it was working in the server!
Wednesday AM just fine. Wednesday afternoon suddenly not working fine. I
swear I didn't change anything!
Is there some way my program can introspect? to see if it is in a thread?
<code>
import threading
import pythoncom
pythoncom.CoInitialize ()
I had my code return threading.currentThread().getName() and it is
"H:\apache2triad". I'm not sure what that tells me, except that it is in
a thread. I think I have a lot to learn about Apache and mod_python.
--
Bob Gailer
510-978-4454
Roger Upole
2006-12-29 21:32:39 UTC
Permalink
Post by Bob Gailer
Post by Tim Golden
[Bob Gailer]
Post by Bob Gailer
OK. I don't know whether its running in a thread. I made no
changes that I'm aware of that would cause the change in
behavior. I will add the call to pythoncom.CoInitialize. I am
not familiar with this method.
This is one of those gotcha's of Win32 COM programming;
you can be happily using some code which runs fine. You
then drop it into a [web server / service / scheduled job]
and lo! you're now running in a thread.
Yeah, but when I said it was working, it was working in the server!
Wednesday AM just fine. Wednesday afternoon suddenly not working fine. I
swear I didn't change anything!
Is there some way my program can introspect? to see if it is in a thread?
I'm not sure (and perhaps someone can advise) whether there's
any harm in *always* calling CoInitialize!
Multiple calls to CoInitialize don't hurt anything. However (and I should have
mentioned this before) you also need to call CoUninitialize yourself at the end
of the thread.

Roger
Bob Gailer
2006-12-29 22:02:24 UTC
Permalink
Post by Roger Upole
Post by Bob Gailer
Post by Tim Golden
[Bob Gailer]
Post by Bob Gailer
OK. I don't know whether its running in a thread. I made no
changes that I'm aware of that would cause the change in
behavior. I will add the call to pythoncom.CoInitialize. I am
not familiar with this method.
This is one of those gotcha's of Win32 COM programming;
you can be happily using some code which runs fine. You
then drop it into a [web server / service / scheduled job]
and lo! you're now running in a thread.
Yeah, but when I said it was working, it was working in the server!
Wednesday AM just fine. Wednesday afternoon suddenly not working fine. I
swear I didn't change anything!
Is there some way my program can introspect? to see if it is in a thread?
I'm not sure (and perhaps someone can advise) whether there's
any harm in *always* calling CoInitialize!
Multiple calls to CoInitialize don't hurt anything. However (and I should have
mentioned this before) you also need to call CoUninitialize yourself at the end
of the thread.
As I mentioned in my response to Tim, the thread name is
"H:\apache2triad". Since this is a long-running python instance I'm not
sure how to tell that the thread has ended. Is there magic to detect
that? And what happens if CoUninitialize does not get called?
--
Bob Gailer
510-978-4454
Roger Upole
2006-12-31 17:50:56 UTC
Permalink
Post by Bob Gailer
Post by Roger Upole
Post by Bob Gailer
Post by Tim Golden
[Bob Gailer]
Post by Bob Gailer
OK. I don't know whether its running in a thread. I made no
changes that I'm aware of that would cause the change in
behavior. I will add the call to pythoncom.CoInitialize. I am
not familiar with this method.
This is one of those gotcha's of Win32 COM programming;
you can be happily using some code which runs fine. You
then drop it into a [web server / service / scheduled job]
and lo! you're now running in a thread.
Yeah, but when I said it was working, it was working in the server!
Wednesday AM just fine. Wednesday afternoon suddenly not working fine. I
swear I didn't change anything!
Is there some way my program can introspect? to see if it is in a thread?
I'm not sure (and perhaps someone can advise) whether there's
any harm in *always* calling CoInitialize!
Multiple calls to CoInitialize don't hurt anything. However (and I should have
mentioned this before) you also need to call CoUninitialize yourself at the end
of the thread.
As I mentioned in my response to Tim, the thread name is
"H:\apache2triad". Since this is a long-running python instance I'm not
sure how to tell that the thread has ended. Is there magic to detect
that? And what happens if CoUninitialize does not get called?
If CoUninitialize doesn't get called for each call to CoInitialize,
you can leak memory. You should be fine if you call CoInit before you
start, and CoUninit when you're done processing.

Roger
Mark Hammond
2007-01-02 03:17:33 UTC
Permalink
Another random comment re CoInitialize in servers...

Depending on your requirements, you may be better off with:

try:
pythoncom.CoInitializeEx(pythoncom.COINIT_MULTITHREADED)
except pythoncom.com_error:
# already initialized.
pass

(and as per Roger's comments, adding a flag to handle CoUninitialize). That
way, you are more likely to get a COM object that can be shared across
multiple threads (eg, grabbing a shared ActiveDirectory connection), and
also handle the possibility someone else has beaten you to the Initialize
using different flags (a distinct possibility in a "plugin" style server
environment.) Also, many server environments, such as Zope and I guess
Apache, use some kind of thread-pool mechanism. Threads are often started
early, and only terminated as the process terminates (or whenever the server
feels the need to recycle threads for whatever reason). For this reason, I
admit that not all code I write ensures CoUninitialize() is always called,
even though I should :)

Mark

Loading...