【问题标题】:Add time delay between every statement of python code在python代码的每条语句之间添加时间延迟
【发布时间】:2018-08-15 19:39:25
【问题描述】:

有没有一种简单的方法可以在 Python 代码的每个语句之间执行时间延迟(例如 time.sleep(3)),而不必在每个语句之间显式编写?

就像下面的 Python 脚本一样,它在 SAP GUI 窗口上执行某些操作。有时,脚本会在前一个语句完成之前继续执行下一个语句。因此,我必须在每个语句之间添加一个时间延迟,以便它正确执行。它正在处理时间延迟,但我最终在每行之间添加了time.sleep(3)。只是想知道是否有更好的方法?

import win32com.client
import time

sapgui = win32com.client.GetObject("SAPGUI").GetScriptingEngine
session = sapgui.FindById("ses[0]")

def add_record(employee_num, start_date, comp_code):
    try:
        time.sleep(3)
        session.findById("wnd[0]/tbar[0]/okcd").text = "/npa40"
        time.sleep(3)
        session.findById("wnd[0]").sendVKey(0)
        time.sleep(3)
        session.findById("wnd[0]/usr/ctxtRP50G-PERNR").text = employee_num
        time.sleep(3)
        session.findById("wnd[0]").sendVKey(0)
        time.sleep(3)
        session.findById("wnd[0]/usr/ctxtRP50G-EINDA").text = start_date
        time.sleep(3)
        session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT/ctxtRP50G-WERKS[1,0]").text = comp_code
        time.sleep(3)
        session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT/ctxtRP50G-PERSG[2,0]").text = "1"
        time.sleep(3)
        session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT/ctxtRP50G-PERSK[3,0]").text = "U1"
        time.sleep(3)
        session.findById("wnd[0]/usr/tblSAPMP50ATC_MENU_EVENT").getAbsoluteRow(0).selected = True
        time.sleep(3)
        return "Pass"
    except:
        return "failed"

【问题讨论】:

  • 你认为什么是“步骤”?
  • 已更正,每一行代码
  • 您会惊讶地发现,实际上只是为了完成一些表面上看起来非常简单的事情,比如作业。
  • 感谢您告诉我们您的 X Y 问题。应该有更好的方法来做到这一点。请向我们展示您的一些麻烦代码!
  • 另外,@chundu:您能否edit您最近对您的问题发表评论的信息?没有它,这个问题很容易被误解,因此到目前为止您收到的大多数答案并没有真正解决您的真正问题。

标签: python win32com sap-gui


【解决方案1】:

执行您所要求的正确方法几乎肯定是使用调试器pdb

想要做你想做的事的正确方法可能完全不同:找到一些告诉你步骤已完成的信号,然后等待那个信号。遇到这样的问题,几乎任何你选择的时间都会有 99% 的时间太长,但仍有 1% 的时间太短。该信号可能是 joining 线程,或 waiting (threadingmultiprocessingCondition,或来自队列的 getting,或 awaiting 协程或未来,或者在 AppleEvent 上设置 sync 标志,或者……这真的取决于你在做什么。


但如果你真的想这样做,你可以使用settrace

def sleeper(frame, event, arg):
    if event == 'line':
        time.sleep(2)
    return sleeper

sys.settrace(sleeper)

一个小问题是解释器使用的行的概念很可能不是你想要的。简而言之,每当 ceval 循环跳转到不同的 lnotab 条目时,就会触发 'line' 跟踪事件(请参阅源代码中的 lnotab_notes.txt 以了解这意味着什么——您可能至少需要对字节码的方式有一个初步的了解至少通过阅读dis 文档来理解这一点)。因此,例如,多行表达式是单行; with 语句的行可能会出现两次,等等。1


而且可能还有一个更大的问题。

有时,脚本会在上一步完全完成之前继续下一步。

我不知道这些步骤是什么,但如果你让整个线程休眠 2 秒,那么你等待的步骤很可能不会取得任何进展,因为线程处于休眠状态。 (例如,您没有循环通过任何异步或 GUI 事件循环,因为您什么也没做。)如果是这样,那么在 2 秒后,它仍然会像以前一样不完整,并且您'会白白浪费 2 秒。


1。如果您的“行”概念更接近the reference docs on lexing and parsing Python 中描述的内容,您可以创建一个导入钩子来遍历 AST,并在每个 body 中的每个列表元素之后添加一个带有 Calltime.sleep(2) 的表达式语句使用模块、定义或复合语句(然后像往常一样编译和执行结果)。

【讨论】:

  • 基于cmets,很明显提问者不想要交互式调试解决方案,他们只想在每一步等待上一步完成。
  • @DanielPryden 但他们不知道如何在每一步等待,以及他们想要解决的方法(当然,这不是一个好的解决方案)是每一个之后睡觉。这展示了如何在没有交互式调试会话的情况下准确地做到这一点,同时也(希望)解释了为什么它不是一个好主意。
【解决方案2】:

您想在程序中发生的任何事情都必须明确说明 - 这是编程的本质。这就像询问您是否可以在不调用print("hello world") 的情况下打印hello world

【讨论】:

  • 这是对的,但在 Python 这样的语言中,现实情况是 很多 的事情在没有明确说明的情况下发生。事实上,在 CPython 中可以使用sys.settrace() 来注册一个函数,该函数将为每一行代码调用。你可能不应该做这样的事情(让调试器为你做),但你可以
【解决方案3】:

我认为在这里给你的最好建议是:不要从“线条”的角度思考,而要从功能的角度思考。

【讨论】:

    【解决方案4】:

    使用调试模式,逐行观察每一行执行。

    【讨论】:

    • 基于cmets,很明显提问者不想要交互式调试解决方案,他们只想在每一步等待上一步完成。
    • 有一个叫做 pdb 的 Python 调试器就是用来做这个的!
    • 依赖于所用编译方法的解决方案被认为是劣质的,原因是@SlahuddinChaudhary
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2015-01-14
    • 2022-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多