import win32com.client from time import sleep def download_url_with_ie(url): """ Given a url, it starts IE, loads the page, gets the HTML. Works only in Win32 with Python Win32com extensions enabled. Needs IE. Why? If you’re forced to work with Brain-dead closed sourceapplications that go to tremendous length to deliver output specific to browsers; and the application has no interface other than a browser; and you want get data into a CSV or XML for further analysis; Note: IE internally formats all HTML to stupid mixed-case, no- quotes-around-attributes syntax. So if you are planning to parse the data, make sure you study the output of this function rather than looking at View-source alone. """ #if you are calling this function in a loop, it is more #efficient to open ie once at the beginning, outside this #function and then use the same instance to go to url’s ie = win32com.client.Dispatch("InternetExplorer.Application") ie.Visible = 1 #make this 0, if you want to hide IE window #IE started ie.Navigate(url) #it takes a little while for page to load. sometimes takes 5 sec. if ie.Busy: sleep(5) #now, we got the page loaded and DOM is filled up #so get the text text = ie.Document.body.innerHTML #text is in unicode, so get it into a string text = unicode(text) text = text.encode('ascii','ignore') #save some memory by quitting IE! **very important** ie.Quit() #return text print text download_url_with_ie('http://www.goermezer.de')
Read from a Microsoft Access database with ADODB
This example demonstrates how to read from a Microsoft Access database
via AdoDB and Python/Pywin32. This code opens a test database and
prints the names of the columns.
import win32com.client connection = win32com.client.Dispatch(r'ADODB.Connection') DSN = 'PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=c:\\pfad\\testdb.mdb;' connection.Open(DSN) recordset = win32com.client.Dispatch(r'ADODB.Recordset') recordset.Open('SELECT * FROM Auftraege', connection, 1, 3) fields_dict = {} for x in range(recordset.Fields.Count): fields_dict[x] = recordset.Fields.Item(x).Name print fields_dict[x], recordset.Fields.Item(x).Value
Calculator automation via sendkeys
This example opens the Windows calculator (calc) and makes some input like using the keyboard.
import win32com.client import win32api shell = win32com.client.Dispatch("WScript.Shell") shell.Run("calc") win32api.Sleep(100) shell.AppActivate("Calculator") win32api.Sleep(100) shell.SendKeys("1{+}") win32api.Sleep(500) shell.SendKeys("2") win32api.Sleep(500) shell.SendKeys("~") # ~ is the same as {ENTER} win32api.Sleep(500) shell.SendKeys("*3") win32api.Sleep(500) shell.SendKeys("~") win32api.Sleep(2500)
Controlling applications via sendkeys
With sendkeys (Python/Pywin32 uses WScript from Windows Scripting Host) one can control applications via shortcuts. eg.
This example first opens Microsoft Outlook, takes the first element, marks the full text and takes it into the clipboard (CTRL + C).
import win32com.client shell = win32com.client.Dispatch("WScript.Shell") shell.Run("outlook") shell.AppActivate("Outlook") shell.SendKeys("^o", 0) # 1 für Pause = true 0 für nein shell.SendKeys("^a", 0) shell.SendKeys("^c", 0)
Here is a list of WScript-commands:
Key | Argument |
BACKSPACE | {BACKSPACE}, {BS}, or {BKSP} |
BREAK | {BREAK} |
CAPS LOCK | {CAPSLOCK} |
DEL or DELETE | {DELETE} or {DEL} |
DOWN ARROW | {DOWN} |
END | {END} |
ENTER | {ENTER} or ~ |
ESC | {ESC} |
HELP | {HELP} |
HOME | {HOME} |
INS or INSERT | {INSERT} or {INS} |
LEFT ARROW | {LEFT} |
NUM LOCK | {NUMLOCK} |
PAGE DOWN | {PGDN} |
PAGE UP | {PGUP} |
PRINT SCREEN | {PRTSC} |
RIGHT ARROW | {RIGHT} |
SCROLL LOCK | {SCROLLLOCK} |
TAB | {TAB} |
UP ARROW | {UP} |
F1 | {F1} |
F2 | {F2} |
F3 | {F3} |
F4 | {F4} |
F5 | {F5} |
F6 | {F6} |
F7 | {F7} |
F8 | {F8} |
F9 | {F9} |
F10 | {F10} |
F11 | {F11} |
F12 | {F12} |
F13 | {F13} |
F14 | {F14} |
F15 | {F15} |
F16 | {F16} |
Steuerung, Shift, ALT und Enter werden wie folgt gesendet:
Key | Special Character |
SHIFT | + |
CTRL | ^ |
ALT | % |
ENTER | ~ |
The documentation of Sendkeys you can find at Microsoft.
Show usable ProgIDs for win32com
This example shows you the available ProgIDs of the Windows applications which are installed and ahould be usable with win32com. My problem is, that most of the ProgIDs are shown, but not all ?!
import win32com.client strComputer = "." objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator") objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2") colItems = objSWbemServices.ExecQuery("Select * from Win32_ProgIDSpecification") for objItem in colItems: print "Caption: ", objItem.Caption print "Check ID: ", objItem.CheckID print "Check Mode: ", objItem.CheckMode print "Description: ", objItem.Description print "Name: ", objItem.Name print "Parent: ", objItem.Parent print "ProgID: ", objItem.ProgID print "Software Element ID: ", objItem.SoftwareElementID print "Software Element State: ", objItem.SoftwareElementState print "Target Operating System: ", objItem.TargetOperatingSystem print "Version: ", objItem.Version print "-------------------------------------------------------------------\n"
Shellwindows
This example prints the name and and pathes of the open windows (Tip: You can get the CLSID with makepy in Pythonwin):
import win32com.client # look in the makepy output for IE for the 'CLSIDToClassMap' # dictionary, and find the entry for 'ShellWindows' clsid='{9BA05972-F6A8-11CF-A442-00A0C90A8F39}' ShellWindows=win32com.client.Dispatch(clsid) for i in range(ShellWindows.Count): print i # this is the titlebar value print ShellWindows[i].LocationName # this is the current URL print ShellWindows[i].LocationURL print
Get all URLs from a webpage
This example shows how to automate Microsoft Internet Explorer with Python/Pywin32.
It
opens a Internet Explorer window, surfs to www.goermezer.de (and waits 3
sec to load the page), and prints all links of the loaded page.
Some links to the Object Model of Microsoft Internet Explorer:
import win32com.client, time ie = win32com.client.Dispatch("InternetExplorer.Application") ie.Visible = 1 ie.Navigate('http://www.goermezer.de') time.sleep(3) #wait 3 sec. print 'You are surfing on', ie.Document.domain print 'And now a list of the Links:' for i in ie.Document.links: print i
A simple Excel to PDF Converter
This is a simple PDF Converter which watches in a directory for
incoming Excel documents and converts them to PDF. Ghostscript and a
Postscript printer has to be installed.
path_to_watch = "D:\\share\\"
before = dict ([(f, None) for f in os.listdir (path_to_watch)]) def convert(filename): tmpfile = path_to_watch + 'tmp\\'+filename+'.ps' if filename[-3:]=='xls': pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED) myExcel = win32com.client.DispatchEx('Excel.Application') Excel = myExcel.Workbooks.Open(path_to_watch+filename, 0, False, 2) Excel.PrintOut(1, 5000, 1, False, 'Rumborak PDF-Writer Plus 1.0 RC5', \ True, False, tmpfile) Excel.Saved = 1 Excel.Close() myExcel.Quit() del Excel del myExcel os.popen('c:\\gs\\gs8.15\\bin\\gswin32c.exe -sDEVICE=pdfwrite -r300 -dNOPAUSE \ -dBATCH -dSAFER -sPAPERSIZE=a4 \ -sOutputFile="'+path_to_watch+filename+'.pdf" "'+tmpfile+'"') #os.remove(path_to_watch+filename) os.remove(tmpfile) pythoncom.CoUninitialize() while 1: time.sleep (0.1) after = dict ([(f, None) for f in os.listdir (path_to_watch)]) added = [f for f in after if not f in before] if added and added[0][-3:]=='xls': starttime = time.clock() print "File ", ", ".join (added), "added to queue" convert(added[0]) stoptime = time.clock() print "OK. It took", stoptime-starttime, 'seconds.\n' before = after
makepy – early u. late binding von COM Objekten (german)
Python nutzt das Modul win32com der Windows-Erweiterung Pywin32 zur Automatisierung von Applikationen über COM (Component ObjectModel). Man spricht hier auch von COM-Automation. Dabei unterscheidet es zwischen early- sowie late-binding. Um nicht zu weit auszuholen, versuche ich es hier einmal kurz auf den Punkt zu bringen:
Late-binding: Python kennt keine Methoden und Attribute der Objektbibliothek, die per COM angesprochen und automatisiert werden soll.
Early-binding: Python kennt alle Methoden und Attribute der Objektbibliothek, die per COM angesprochen und automatisiert werden soll.
Was macht das für einen Unterschied ?
Nun, zunächst hat das early-binding Performance-Vorteile bei der Ausführung der Python-Programme. Aber dafür müssen einmalig vor Ausführen der Anwendungen sog. Cachefiles für die genutzten Bibliotheken erzeugt werden. Das kann je nach größe und Anzahl der Bibliothek recht lange dauern. Ein Trost ist, dass dieser Prozess nur ein einziges Mal durchgeführt werden muss. Danach sind bei jeder Ausführung der Python-Programme die Cachefiles noch
vorhanden und werden genutzt.
Ein weiterer Vorteil des early-bindings betrifft das Editieren im Pythonwin-Editor. Da durch die Cachefiles alle Methoden und Attribute Python bekannt sind, sind sie auch Pythonwin bekannt. Das bedeutet, dass während des Editierens nach den ersten Buchstaben
der Pythoncode vervollständigt wird. Das macht das Programmieren wesentlich komfortabler.
Man kann aber generell keine Empfehlung abgeben, ob man early- oder late-binding nutzen soll. Es existieren Anwendungen wie z.B. CATIA V5, die mit early-binding so ihre Probleme haben. In solchen Fällen muss das late-binding genutzt werden.
Wie werden die Cachefiles erzeugt und das early-binding genutzt ?
Mir sind drei Wege bekannt:
1. Einmaliger Aufruf des Programms c:\python23\Lib\site-packages\win32com\client\makepy.py und Auswahl der zu automatisierenden Objektbibliothek.
2. Einmaliger Aufruf des Programms c:\python23Libsite-packageswin32comclientmakepy.py mit Name der zu automatisierenden Objektbibliothek als Argument. Z.B. makepy.py “Microsoft Word 10.0 Object Library”
3. dynamisches generieren der Cachefiles. Dazu sind 2 Zeilen Code im Python-Programm nötig, die durch das Aufrufen von makepy.py mit dem Argument -i ausgegeben werden. Z.B:
makepy.py -i "Microsoft Word 10.0 Object Library"
liefert folgende Ausgabe:
# Use these commands in Python code to auto generate .py support from win32com.client import gencache gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 2)
Bei der dynamischen Methode werden beim ersten Aufruf des Programms die Cachefiles einmalig erzeugt und bleiben erhalten und von Python- Programmen genutzt, bis sie manuell vom User gelöscht werden. Bei ersteren beiden werden Sie einmalig manuell erzeugt. Das bedeutet auch: falls die Cachefiles, warum auch immer, gelöscht werden, werden sie nur von der
dynamischen Methode wieder neu erzeugt.
Wie nutzt man das late-binding ?
Wie eingangs erwähnt, haben es manche Anwendungen schwer mit early-binding. In solchen Fällen muss das late-binding genutzt werden. Man erzwingt es durch einen “dynamic Dispatch”. Dazu ruft man im Python-Programm die COM-Bibliothek der Applikation (hier Outlook) wie folgt auf:
o = win32com.client.dynamic.Dispatch("Outlook.Application")
Folgender Aufruf nutzt hingegen (falls vorhanden) das Cachefile für Outlook:
o = win32com.client.Dispatch("Outlook.Application")
Falls die Cachefiles nicht vorhanden sind (und ein makepy zuvor nicht erfolgt ist), erfolgt ebenfalls ein late-binding.
Mehr und Ausführlicheres zu Python und COM ist auf einem Probekapitel des Buchs Python Programming on Win32 zu finden.
Automating Microsoft Outlook
For Outlook automation it is nesseccary to use the makepy utility. You do this either from the tools menu of the Pythonwin-Editor (installed with Pywin32 or ActivePython) or you call the file c:\python23\Lib\site-packages\win32com\client\makepy.py. You then have to select the Outlook Object Library (“Microsoft Outlook 10.0 Object Library” for Office 10.0 or known as Office XP).
After that Python generates cachefiles into the directory c:\python23\Lib\site-packages\win32com\gen_py or c:\temp\gen_py to tell Python more about the Outlook object library.
Here is a well known example which dumps all adressbook entries from your default adressbook:
import codecs, win32com.client # This example dumps the items in the default address book # needed for converting Unicode->Ansi (in local system codepage) DecodeUnicodeString = lambda x: codecs.latin_1_encode(x)[0] def DumpDefaultAddressBook(): # Create instance of Outlook o = win32com.client.Dispatch("Outlook.Application") mapi = o.GetNamespace("MAPI") folder = mapi.GetDefaultFolder(win32com.client.constants.olFolderContacts) print "The default address book contains",folder.Items.Count,"items" # see Outlook object model for more available properties on ContactItem objects attributes = [ 'FullName', 'Email1Address'] for i in range(1,folder.Items.Count+1): print "~~~ Entry %d ~~~" % i item = folder.Items[i] for attribute in attributes: print attribute, eval('item.%s' % attribute) o = None DumpDefaultAddressBook()