python windows winapi selenium pywin32

¿Cuál es la mejor manera de interactuar con los cuadros de diálogo de SO nativos ya abiertos como(Guardar AS) usando Python?



windows winapi (2)

¿Hay alguna manera eficiente de usar cualquier módulo de Python como PyWind32 para interactuar con cuadros de diálogo de SO nativos ya existentes como los cuadros de ''Guardar como''?

Intenté buscar en Google pero no recibí ayuda.

EDITAR:

1: El cuadro de diálogo Guardar como se activa cuando el usuario hace clic en un cuadro de diálogo Guardar como en una aplicación web.

2: Cualquier sugerencia es bienvenida para manejar cualquier cuadro de diálogo de SO nativo que ya se haya activado usando Python. (No es necesario ser específico de Selenium webdriver, estoy buscando una sugerencia genérica).

(Cuando estaba publicando la pregunta, pensé que "interactuar con un cuadro de diálogo" significará implícitamente que es una existente, como si fuera capaz de crear una, entonces seguramente puedo interactuar con ella, ya que está bajo el control de mis programas. Después de leer las primeras 2 respuestas, me di cuenta de que no estaba explícitamente claro. Por eso el EDIT)

Gracias


Hay un módulo de Python llamado win32ui. Se encuentra en el paquete de extensiones de Python para Windows . Desea la función CreateFileDialog.

Documentación

Editar: Este es un ejemplo de diálogo de guardar. Verifique la documentación para las otras configuraciones.

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


Mientras buscaba una posible solución para esto, encontré varias soluciones sobre SO y otras. Algunos de ellos usaban AutoIT , o el perfil de los navegadores de edición para hacer que almacenara el archivo directamente sin un aviso.

Encontré toda esta solución demasiado específica como si pudiera solucionar el problema del diálogo Guardar como editando el perfil del navegador, pero si más adelante necesita manejar alguna otra ventana, entonces se queda atascado. Para usar AutoIT es excesivo, esto colisiona directamente por el hecho de elegir Python para hacer esta tarea. (Me refiero a Python es en sí mismo tan poderoso, dependiendo de alguna otra herramienta es estricto NO NO para cualquier Pythonist)

Así que después de una larga búsqueda de una posible solución genérica para este problema que no solo sirve a cualquiera que esté tratando de manejar cualquier cuadro de diálogo de SO nativo como ''Guardar como'', ''Subir archivo'', etc. en el proceso de automatizar una aplicación web usando selenio controlador web, sino también a cualquiera que quiera interactuar con una ventana específica utilizando solo API de Python .

Esta solución hace uso de los módulos Win32gui , SendKeys de Python . Explicaré primero un método genérico para obtener cualquier ventana deseada y luego una pequeña adición de código que también lo hará utilizable al automatizar una aplicación web usando Selenium Webdriver.

Solución Genérica ::

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

Para usar este código, debe proporcionar una cadena que es el nombre de la ventana que desea obtener, que en este caso es ''Guardar como''. De manera similar, puede proporcionar cualquier nombre y enfocar esa ventana. Una vez que tiene el foco de la ventana deseada, puede usar el módulo SendKeys para enviar los trazos de tecla a la ventana, que en este caso incluye el envío de la ruta del archivo donde desea guardar el archivo y ENTER .

Específico para Selenium Webdriver ::

El segmento de código especificado anteriormente se puede usar para manejar cuadros de diálogo de SO nativos que se activan a través de una aplicación web durante la automatización usando Selenium Webdriver con la adición de un poco de código.

El problema al que me enfrenté al usar este código es que una vez que su código de automatización hace clic en cualquier Web Element que activa una ventana de diálogo del sistema operativo nativo, el control se atascará en ese punto esperando cualquier acción en la ventana de diálogo del sistema operativo nativo. Entonces, básicamente estás estancado en este punto.

El trabajo consiste en generar un nuevo thread utilizando el módulo de threading Python y usarlo para hacer clic en el Web Element para activar el cuadro de diálogo del sistema operativo nativo y el hilo padre se moverá normalmente para encontrar la ventana utilizando el código que mostré arriba.

#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

NOTA::

Cuando utilice el código anterior para automatizar una aplicación web, verifique el nombre de la ventana que desea buscar y páselo a find_window_wildcard() . El nombre de las ventanas depende del navegador. Por ejemplo, una ventana que se activa al hacer clic en un Elemento para cargar un archivo se denomina ''Carga de archivos'' en Firefox y Abrir en Chrome . Utiliza Python2.7

Espero que esto ayude a cualquiera que esté buscando una solución similar, ya sea para usarla en cualquier forma genérica o para automatizar una aplicación web.

EDITAR:

Si está intentando ejecutar su código a través de argumentos de línea de comando, intente usar la Win32gui para encontrar la ventana usando Win32gui y use el hilo del programa original para hacer clic en el elemento (que se hace clic aquí usando el hilo). El motivo es que la biblioteca urllib arrojará un error al crear una nueva conexión utilizando el hilo.

Referencias ::

ASI pregunta

SenKeys

Win32gui