win32com und BSTR

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

also mit der backslachgeschichte kenne ich mich aus^^

entweder:
path=r"c:\erster\ordner"
oder:
path="c:\\erster\\ordner"

die gänsefüßchen können immer durch apostrophe ausgewechselt werden.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Buell hat geschrieben:

Code: Alles auswählen

erg = cam.SaveImage(r'S:\Reiner\MaxIm\1.fit')
Mir ist allerdings nicht so ganz klar übergibt man SaveImage den Ziel oder den Quellpfad? Bei Zielpfad würde das r natürlich vollkommen sinnlos sein, denn auf eine zu schreibende Datei nur einen Lesezugriff zu geben klingt irgendwie unlogisch.
Das r hat in diesem Fall nichts mit 'read' zu tun sondern sagt, dass ein raw string folgt, das heisst ein String, in dem die '\' nicht interpretiert werden:

Code: Alles auswählen

>>> print 'C:\verzeichnis\name\datei.txt'
C:
  erzeichnis
ame\datei.txt
>>> print 'C:\\verzeichnis\\name\\datei.txt'
C:\verzeichnis\name\datei.txt
>>> print r'C:\verzeichnis\name\datei.txt'
C:\verzeichnis\name\datei.txt
>>> print r'C:\\verzeichnis\\name\\datei.txt'
C:\\verzeichnis\\name\\datei.txt
EDIT: Ich sehe jetzt erst murphs Post...
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

OK, das mit dem r hatte ich als "read" interpretiert, so ergibt das natürlich Sinn und die Backslash Geschichte wäre beantwortet. Bleibt eigentlich nur noch als Fehler, was ich vorher auch schon geschrieben habe, mit dem Rückgabewert der irgendwo hin muss.
PureImpact
User
Beiträge: 15
Registriert: Donnerstag 13. April 2006, 19:20

Hallo Leute,

wollte euch nur mitteilen dass das Problem mittlerweile geloest wurde.
Wie bereits gesagt, ein Entwickler von MaxIm DL hat sich Python +
pywin32 installiert und daraufhin hat Mark Hammond sich ne Trial-Version
von MaxIm DL installiert und die beiden haben den Fehler gefunden.

FYI, Auszuege aus den emails:

Mark:
---
I did that (mainly due to the effort by him trying to track this down!)

The problem turns out to be:

pywintypes.com_error: (-2147352567, 'Exception occurred.', (65535, 'MaxIm DL
4', 'Invalid Input', None, 0, 0), None)

This exception is being raised by Python calling Invoke with the correct
dispid, but with only INVOKE_PROPERTYGET and *not* DISPATCH_METHOD. The
"problem" is that Python's syntax does does distinguish between a property
and a method - so:

ob.foo()

is (roughly) equivalent to:

func_ob = getattr(ob, "foo")
func_ob()

so win32com struggles around this, with the short story being that only
certain error values are "acceptable" when a 'method' is accessed as a
'property'.

Currently, pywin32 only accepts the hresults (DISP_E_MEMBERNOTFOUND,
DISP_E_BADPARAMCOUNT, DISP_E_PARAMNOTOPTIONAL, DISP_E_TYPEMISMATCH and
E_INVALIDARG). MaxIM returns DISP_E_EXCEPTION, which is not in this list -
and actually should not be. DISP_E_EXCEPTION means extra exception info is
returned, as reflected in the final part of the above exception. Ideally,
pywin32 would indirect into the COM excepinfo structure to find the real
error info. Fortunately for me <wink>, even if pywin32 did sniff deeper, it
would find an error result of -1 (65535) or zero - so would still fail to
find one of its 'acceptable' error results to make the distinction between
'property' and 'method'.

So - the end result is that MaxIM really needs to return a more sane result
when only PROPERTYGET is (or zero args are) requested. If it is more
convenient for MaxIM to continue to return DISP_E_EXCEPTION and set the real
error in the extended error info, I could agree to make pywin32 handle that
case ;)
---

Antwort von MaxIm DL-Jungs:
---
Well, all this is most instructive. Among other things it explains why
MaxIm DL's Document.SaveFile method is usable from Python, while
CCDCamera.SaveImage is not. SaveFile is declared as type void, so MFC's
COleDispatchImpl::Invoke() detects the attempt to access it as a property
and returns DISP_E_BADPARAMCOUNT, causing pywin32 to revise how it calls it.
But SaveImage is declared as returning a bool, so pywin32's tentative (and,
from MaxIm DL's perspective, erroneous) call without arguments gets through
into our implementation of the function, which then objects to the VT_ERROR
value that CCmdTarget::PushStackArgs() had supplied for lack of anything
from the client.

Reiner and I had independently suspected the result type might have
something to do with it, but I at least had concentrated on the appearance
of the call, i.e., whether the result was being 'used' or not. This was
irrelevant, of course.

Reading MFC\SRC\OLEDISP1.CPP more closely than I ever remember doing before,
it also becomes clears that any method having a parameter of type other than
VARIANT will also fail with DISP_E_BADPARAMCOUNT, causing pywin32 to
recover. So by my reckoning, the only MaxIm DL methods that will *not* work
when called from Python are:
Document.SetFITSKey
Document.GetFITSKey
CCDCamera.SaveImage
CCDCamera.SetFITSKey
Application.CalAddBias
Application.CalAddDark
Application.CalAddFlat

All others either return void, or have at least one non-VARIANT argument, or
both.

The question remains, what to do about it? I don't think the C++
implementation of a method (that is, a C++ method of a CCmdTarget-derived
class vectored to from a dispatch table) can obtain the wFlags value passed
to Invoke(), so I can't distinguish this situation from one where the caller
specified DISPATCH_METHOD but failed to provide an argument. This means the
behaviour of our COM interface would have to change, presenting possible
backward-compatibility issues to [non-Python] users. Even more germane, I
don't know how my code can return an error indicator other than
DISP_E_EXCEPTION (which we don't do directly anyway; it's the work of
AfxThrowOleDispatchException()). But I'm willing to be instructed if anyone
knows a way... :-)

Another possibility is to change the calling sequence, or return type, for
the methods listed above, e.g., by changing VT_VARIANT to VT_LPSTR in those
cases where only strings are expected. But this is sure to cause grief for
some users (even though we have had complained about our use of variants in
this context). A less draconian solution is to provide alternate methods
with more pywin32-friendly calling sequences and perhaps eventually
deprecate the troublesome ones. But I should state that my boss is on
record as saying he wants to minimize the impact on MaxIm DL.
---

...und kurze Zeit spaeter ein addendum:
---
Is it too late to recover any of my lost self-respect? Of course the answer
is AfxThrowOleException().

I'm now in favour of adding code like

if ( FilePath.vt == VT_ERROR )
AfxThrowOleException( DISP_E_BADPARAMCOUNT );

to the troublesome methods I listed previously, and not worry about the fact
that this changes prior behaviour. After all, the code of anyone who
notices this change wasn't working before anyway.

I already tried this, and Reiner's script (and Mark's pywin32) work like a
charm.
---

Die naechste Version von MaxIm DL (v4.54) wird somit Python/pywin32-
compliant sein :D

Besten Dank an alle die sich hier auf dem Forum an dem Raetsel beteiligt
haben. In der Hoffnung dass dieser Thread dem ein oder anderen in
Zukunft helfen wird, poste ich es mal, damit Google es findet. Oh man,
sehr gutes "Deutsch" mal wieder :lol:

Gruss,
Reiner
Antworten