当前位置: 首页 > 面试题库 >

与使用Python与已打开的本机OS对话框(如(另存为AS))进行交互的最佳方法是什么?

花烨
2023-03-14
问题内容

是否有任何有效的方式使用任何Python模块,例如PyWind32与“另存为”框等现有的本机OS对话框进行交互?

我尝试在Google上搜索,但没有帮助。

编辑:

1:当用户单击Web应用程序上的“另存为”对话框时,将触发“另存为”对话框。

2:欢迎提出任何建议来处理已使用Python触发的任何本机OS对话框。(不必特定于Selenium Webdriver,我正在寻找通用建议。)

(当我发布问题时,我认为通过“与对话框交互”将隐含意味着它是现有的,就好像我能够创建一个对话框一样,然后可以在程序控制下与之进行交互。阅读了前两个答案后,我意识到我并不清楚。这就是为什么EDIT)

谢谢


问题答案:

在为此寻找可能的解决方案时,我遇到了关于SO和其他方面的几种解决方案。其中一些使用AutoIT,或编辑浏览器配置文件以使其直接存储文件而没有提示。

我发现所有这些解决方案都太具体了,以至于您可以通过编辑浏览器配置文件来解决“另存为”对话框的问题,但是如果以后需要处理其他窗口,则会遇到麻烦。因为使用AutoIT是多余的,这直接冲突了我选择Python执行此任务的事实。(我是Python说它本身是如此强大,取决于任何其他工具,对于任何Pythonist来说都是严格禁止的)

因此,在长期寻找这一问题的可能解决方案之后,该解决方案不仅可以为使用硒自动化Web应用程序的任何希望处理“本机OS”对话框(如“另存为”,“文件上传”等)的人提供服务。
Web驱动程序,也适用于希望仅使用PythonAPI 与特定窗口进行交互的任何人。

该解决方案利用了Win32guiSendKeys的模块Python。我将首先说明一种通用方法,该方法可以保留所需的任何窗口,然后再添加少量代码,这将在使用Selenium
Webdriver自动执行Web应用程序时使此方法可用。

通用解决方案 ::

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

要使用此代码,您需要提供一个字符串,该字符串是您要获取的窗口的名称,在这种情况下为“另存为”。因此,类似地,您可以提供任何名称并使该窗口聚焦。有了所需窗口的焦点后,便可以使用SendKeys模块将击键发送到窗口,在这种情况下,包括将文件路径发送到要保存文件的位置和ENTER

特定于Selenium Webdriver ::

上面指定的代码段可用于处理本机OS对话框,这些对话框是在自动化过程中通过使用Selenium Webdriver少量的代码通过Web应用程序触发的。

在使用此代码时,您将遇到的问题是,一旦您的自动化代码单击了任何Web Element会触发本机OS对话框窗口的代码,控件就会停留在该位置,等待本机OS对话框窗口上的任何操作。因此,基本上,您在这一点上处于困境。

解决方法是生成一个新的threadusing Python threading模块,并使用它单击Web Element触发本机OS对话框,并且您的父线程将正常运行以使用上面显示的代码查找窗口。

#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

注意::

在自动化Web应用程序中使用上述代码时,请检查您要查找的窗口的名称并将其传递给find_window_wildcard()。Windows的名称取决于浏览器。例如,当您单击元素上载文件时触发的窗口称为“文件上载”
Firefox和“打开中” Chrome。用途Python2.7

我希望这对正在寻找类似解决方案的任何人(无论是以任何通用形式使用它还是使Web应用程序自动化)都将有所帮助。

编辑:

如果您尝试通过命令行参数运行代码,则尝试使用该线程来查找窗口,Win32gui并使用原始程序线程单击该元素(在此处使用该线程单击该元素)。原因是urllib库在使用线程创建新连接时会引发错误。)

参考文献:

SendKeys

Win32gui



 类似资料:
  • 问题内容: 继承人的HTML: 这是js: 这是执行此操作的最佳方法吗?似乎有一种更好的方法可以在不访问DOM的情况下将其打开,但是我不确定该如何处理。上面的代码有效,我只是想知道这是否是我应该这样做的方法。欢迎任何输入。 问题答案: 这里的“最佳实践”是模糊的基础。如果它可读并且可以工作,那么IMO,您就90%了,这可能还不错。 也就是说,“角度方式”是将DOM操作保持在控制器之外,并使用依赖项

  • 以前,我是这个AutoIT的新手,我不熟悉这个,只是谷歌需要完成我的任务,如果我的AtotoIt有任何错误,请更正它 我的autoIT代码(参考自http://qtp-help.blogspot.in/2009/07/selenium-handle-dialogs.html#handle_save_dialog) 我的java代码 请帮忙解决

  • 问题内容: 解决此问题的最佳方法是: 打开文件进行读取,但前提是尚未打开文件进行写入 打开文件进行写入,但前提是尚未打开文件进行读取或写入 内置函数的工作方式如下 scr.txt现在包含“ 111”。 scr.txt已被覆盖,现在包含“ 222”(在Windows上为Python 2.4)。 该解决方案应在同一进程内工作(如上例所示),以及在另一个进程打开文件时。 如果崩溃的程序无法使锁保持打开状

  • 问题内容: 我正在尝试使用python中的Selenium模块从 一个网站生成文本列表,将其保存在目录中,然后浏览至另一 站点上的该文本列表以提交它。 我将脚本分为两个部分:1.获取元数据和2.订购数据。 除了最后一 件事,我已经成功完成了第1部分中的脚本:选择保存刚刚生成的元数据文件。我将其留给第二 部分工作,希望我会偶然发现答案,但是 当弹出选择文件的弹出窗口时,我只是遇到了同样的问题。 在文

  • 问题内容: 我对swig中的typemap和如何使用数组感到迷茫。我准备了一个使用swig在java和c之间使用数组的工作示例,但是我不知道这是否是正确的方法。 基本上,我想将字节数组从Java 传递给c作为“ signed char *” +它的大小,在c中对其进行修改并查看java中的更改,并在c中创建一个数组并在Java中使用它。 *在C中被修改为Java或其他的缓冲区?](http://c