2013-06-21 6 views
5

Gibt es einen effizienten Weg mit jedem Python-Modul wie PyWind32 mit bereits bestehenden Native-OS-Dialogfeldern wie 'Speichern unter' zu interagieren?Welches ist der beste Weg, um mit bereits geöffneten nativen OS-Dialogfeldern wie (Save AS) mit Python zu interagieren?

Ich habe versucht, auf Google aber keine Hilfe zu suchen.

EDIT:

1: Das Dialogfeld Speichern unter ausgelöst wird, wenn Benutzer auf einem Dialogfeld Speichern unter auf einer Web-Anwendung klickt.

. 2: Jeder Vorschlag sind willkommen keine native OS Dialogfelder zu behandeln, die mit Python bereits ausgelöst werden (nicht zu Selen WebDriver spezifisch zu sein brauche, ich bin auf der Suche für einen allgemeinen Vorschlag.)

(Als ich posten die Frage Ich dachte, dass durch die Interaktion mit einer Dialogbox implizit bedeuten würde, dass es eine existierende ist, als ob ich in der Lage wäre, eine zu erstellen, dann kann ich sicher mit ihr interagieren, wie es unter meiner Programmsteuerung ist 2 Antworten, die ich erkannte ich nicht explizit klar war. das ist, warum die EDIT)

Dank

+0

Welche Art von Interaktion du versuchst es zu tun? –

+0

@DavidHeffernan Ich habe eine Webanwendung mit triggert ein neues Speichern als Dialogfeld.Ich muss in dem Sinne interagieren, dass ich auf verschiedene Optionen im Dialog klicken muss und den Zielpfad und den Dateinamen zum Speichern eingeben muss. – abhi

+0

Warum der Downvote – abhi

Antwort

5

Während ich nach einer möglichen Lösung für dieses suchte, stieß ich auf mehrere Lösungen auf SO und anders. Einige von ihnen verwendeten AutoIT oder das Bearbeiten von Browserprofilen, damit die Datei direkt ohne Eingabeaufforderung gespeichert wurde.

Ich fand alle diese Lösung zu spezifisch, wie Sie das Problem für den Speichern unter Dialog durch Bearbeiten des Browserprofils beheben können, aber wenn Sie später mit einem anderen Fenster umgehen müssen, dann stecken Sie fest. Für die Verwendung AutoIT ist Overkill, kollidiert dies direkt für die Tatsache, dass ich Python, um diese Aufgabe zu tun wählen. (Ich meine Python ist selbst so mächtig, abhängig von einem anderen Werkzeug ist streng kein NEIN für jeden Pythonist)

So nach einer langen Suche nach einer möglichen generischen Lösung für dieses Problem, das nicht nur dient jemand, der zu handhaben sucht alle nativen OS-Dialogfelder wie "Speichern unter", "Datei-Upload" usw. bei der Automatisierung einer Web-Anwendung mithilfe des Selen-Web-Treibers, aber auch bei allen, die nur mit Python APIs interagieren möchten.

Diese Lösung verwendet Win32gui, Module von Python. Ich werde zuerst eine generische Methode erklären, um jedes gewünschte Fenster zu erhalten, dann einen kleinen Codezusatz, der dies auch während der Automatisierung einer Webanwendung mit Selenium Webdriver nutzbar macht.

generische Lösung ::

import win32gui 
import re 
import SendKeys 

class WindowFinder: 
"""Class to find and make focus on a particular Native OS dialog/Window """ 
    def __init__ (self): 
     self._handle = None 

    def find_window(self, class_name, window_name = None): 
    """Pass a window class name & window name directly if known to get the window """ 
     self._handle = win32gui.FindWindow(class_name, window_name) 

    def _window_enum_callback(self, hwnd, wildcard): 
    '''Call back func which checks each open window and matches the name of window using reg ex''' 
     if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) != None: 
      self._handle = hwnd 

    def find_window_wildcard(self, wildcard): 
""" This function takes a string as input and calls EnumWindows to enumerate through all open windows """ 

    self._handle = None 
     win32gui.EnumWindows(self._window_enum_callback, wildcard) 

    def set_foreground(self): 
    """Get the focus on the desired open window""" 
     win32gui.SetForegroundWindow(self._handle) 

win = WindowFinder() 
win.find_window_wildcard(".*Save As.*") 
win.set_foreground() 
path = "D:\\File.txt"   #Path of the file you want to Save 
ent = "{ENTER}"     #Enter key stroke. 
SendKeys.SendKeys(path)   #Use SendKeys to send path string to Save As dialog 
SendKeys.SendKeys(ent)   #Use SendKeys to send ENTER key stroke to Save As dialog 

diesen Code verwenden Sie eine Zeichenfolge zur Verfügung stellen müssen, die den Namen des Fensters Sie erhalten möchten, die in diesem Fall ‚Speichern unter‘. In gleicher Weise können Sie einen beliebigen Namen angeben und das Fenster fokussieren. Sobald Sie den Fokus des gewünschten Fensters haben, können Sie das Modul SendKeys verwenden, um Schlüsselstriche an das Fenster zu senden, das in diesem Fall den Dateipfad zum Speichern der Datei und ENTER enthält.

Spezifisch für Selen WebDriver ::

Das oben angegebene Codesegment verwendet werden kann native OS Dialogfelder zu behandeln, die bei der Automatisierung über eine Web-Anwendung ausgelöst werden, unter Verwendung von Selenium Webdriver mit der Zugabe von wenig Code . Das Problem, mit dem Sie bei der Verwendung dieses Codes konfrontiert werden, ist, dass Ihr Steuerelement, sobald es auf ein Web Element klickt, das ein natives Betriebssystemdialogfenster auslöst, an diesem Punkt festsitzt und auf eine Aktion im nativen Betriebssystemdialog wartet Fenster. Also im Grunde steckst du an diesem Punkt fest.

Die Arbeit ist um ein neues thread mit Pythonthreading Modul zu erzeugen, und verwenden Sie es auf dem Web Element klicken, um das native OS-Dialogfeld und Ihre Muttergewinde auslösen wird in der Regel bewegen auf das Fenster zu finden, den Code I zeigte über.

#Assume that at this point you are on the page where you need to click on a Web Element to trigger native OS window/dialog box 

def _action_on_trigger_element(_element): 
    _element.click() 

trigger_element = driver.find_element_by_id('ID of the Web Element which triggers the window') 
th = threading.Thread(target = _action_on_trigger_element, args = [trigger_element]) #Thread is created here to call private func to click on Save button 
th.start()       #Thread starts execution here 
time.sleep(1)      #Simple Thread Synchronization handle this case.   

#Call WindowFinder Class 
win = WindowFinder() 
win.find_window_wildcard(".*Save As.*") 
win.set_foreground() 
path = "D:\\File.txt"   #Path of the file you want to Save 
ent = "{ENTER}"     #Enter key stroke. 
SendKeys.SendKeys(path)   #Use SendKeys to send path string to Save As dialog 
SendKeys.SendKeys(ent)   #Use SendKeys to send ENTER key stroke to Save As dialog 

#At this point the native OS window is interacted with and closed after passing a key stroke ENTER. 
# Go forward with what ever your Automation code is doing after this point 

HINWEIS ::

Wenn bei der Automatisierung einer Web-Anwendung den obigen Code verwenden, prüfen Sie den Namen des Fensters Sie suchen möchten und geben das zu find_window_wildcard(). Der Name von Windows ist Browser abhängig. Z.B. Ein Fenster, das ausgelöst wird, wenn Sie auf ein Element zum Hochladen einer Datei klicken, heißt "Datei hochladen" in Firefox und Öffnen in Chrome. Verwendet Python2.7

Ich hoffe, dass dies jemand helfen wird, der nach einer ähnlichen Lösung sucht, ob es in irgendeiner generischen Form oder in der Automatisierung einer Webanwendung verwendet wird.

EDIT:

Wenn Sie versuchen, Ihren Code über die Befehlszeilenargumente dann versuchen zu laufen, den Faden zu verwenden, um das Fenster zu finden Win32gui verwenden und den ursprünglichen Programm-Thread verwenden, um auf dem Element zu klicken (das ist hier mit dem Thread geklickt). Der Grund, die urllib Bibliothek wird einen Fehler werfen, während eine neue Verbindung mit dem Gewinde zu schaffen.)

Referenzen ::

SO Question

SenKeys

Win32gui

2

Es gibt ein Python-Modul namens win32ui. Es ist in der Python for Windows extensions Paket gefunden. Sie möchten die CreateFileDialog-Funktion.

Documentation

Edit: Dies ist ein Dialog Beispiel speichern. Überprüfen Sie die Dokumentation für die anderen Einstellungen.

import win32ui 

if __name__ == "__main__": 
    select_dlg = win32ui.CreateFileDialog(0, ".txt", "default_name", 0, "TXT Files (*.txt)|*.txt|All Files (*.*)|*.*|") 
    select_dlg.DoModal() 

    selected_file = select_dlg.GetPathName() 
    print selected_file 
+0

Ich muss kein neues Speichern unter Dialogfeld erstellen, sondern mit einem bereits vorhandenen interagieren. Können Sie mir einen Ansatz vorschlagen? – abhi