首页 > 解决方案 > Python代码:赋值前引用的局部变量

问题描述

我在 python 2.7 中有以下程序来启动网页并进行活动。我已经解析了网页的 HTML DOM,并且能够在通过 PyCharm IDE 或通过使用 PyInstaller 创建的 Exe 或通过包装 Exe 的 bat 文件启动时完成这项工作。

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
import time
import sys


def main():

    try:

        mgmt_console_server_name = sys.argv[1]
        user_session_to_terminate = sys.argv[2]

        # Phase 1: Launch a browser and open the management console page
        # Using IE to access web
        driver = webdriver.Ie('IEDriverServer32.exe')
        return_code = 0

        # Open the management console page.
        driver.get("http://" + mgmt_console_server_name + ":8183/mgmt/security/login.html")

        # Phase 2: Enter the LDAP credentials and hit enter
        # Select the username and the password text boxes
        username = driver.find_element_by_class_name('gwt-TextBox')
        password = driver.find_element_by_class_name('gwt-PasswordTextBox')

        # Send username information
        username.send_keys('sa-tcnxbot-gds')

        # Send password information
        password.send_keys('zzzzzzzzz')

        # Login to Teamcenter management console with the above set credentials.
        signinbutton = driver.find_element_by_class_name('GFHWBTICII')
        signinbutton.click()

        # Phase 3: Click on the 'TcServer' component to reach the UI where we can find and kill the user sessions.
        # We are now in the main page. We need to wait till we find an XML element by the ID
        # 'Console'. This signifies that the page has loaded. And we wait at the maximum of 20 seconds.
        WebDriverWait(driver, 20).until(ec.presence_of_element_located((By.ID, "Console")))

        # We find the XML element whose InnerHTML is 'Tc Server'.
        tcserverelement = driver.find_element_by_xpath("//div[text()='Tc Server']")

        # We then find its immediate parent, which is the clickable element and finally click it.
        tcserverclickableelement = tcserverelement.find_element_by_xpath('..')
        tcserverclickableelement.click()

        # Phase 4: We enter the user id whose session is to be terminated in the search field and hit the search.
        WebDriverWait(driver, 20).until(ec.presence_of_element_located((By.XPATH, "//div[text()='Assigned User:']")))

        # We are at the HTML element that has the text 'Assigned User:'
        assigneduserelement = driver.find_element_by_xpath("//div[text()='Assigned User:']")
        # print(assigneduserelement)
        # An immediate parent of this HTML element is the TD element.
        assigneduserelementparent = assigneduserelement.find_element_by_xpath('..')
        # print(assigneduserelementparent)

        # An immediate sibling of this TD HTML element is another TD element which contains INPUT HTML element.
        assigneduserelementparent.find_element_by_xpath("//TD/following-sibling::TD")
        # print(assigneduserelementparent_sibling)

        # assignedusertextbox = assigneduserelementparent_sibling.find_elements_by_xpath(".//*")
        # print(assignedusertextbox[0])

        # Send username information
        driver.find_elements_by_class_name('gwt-TextBox')[1].send_keys(user_session_to_terminate)

        search_button = driver.find_element_by_xpath("//button[text()='Search']")
        # We then find its immediate parent, which is the Search button and finally click it.
        search_button.click()
        time.sleep(4)

        # There would be three cases here.
        # Case 1: The input user has no sessions on his name.
        # Case 2: The input user has one session on his name.
        # Case 3: The input user has more than one sessions on his name.

        # Case 1: This should be one of the table header elements containing the list of servers assigned to the user.
        assigned_server_rows = driver.find_elements_by_xpath("//div[text()='Assigned']")

        if len(assigned_server_rows) == 0:
            return_code = 4
        else:
            # Case 2 and Case 3:
            for each_assigned_server in assigned_server_rows:
                print each_assigned_server.tag_name

                assigned_server_parent_td = each_assigned_server.find_element_by_xpath('..')  # td
                print assigned_server_parent_td.tag_name
                assigned_server_parent_td.click()

                # assigned_server_parent_tr = assigned_server_parent_td.find_element_by_xpath('..')  #tr
                # print assigned_server_parent_tr.tag_name

                # assigned_server_parent_tr.click()

                shutdown_button_element = driver.find_element_by_xpath("//button[text()='Shutdown Server']")
                shutdown_button_element.click()

                time.sleep(2)
                main_page = driver.window_handles[0]
                alert_window = driver.switch_to.alert
                alert_window.accept()
                driver.switch_to.window(main_page)
    except:
        return_code = 1
    finally:
        driver.quit()

    if return_code == 0:
        print('=> Successfully terminated sessions for the user ' + user_session_to_terminate)
    elif return_code == 4:
        print('=> There are no sessions assigned to the user ' + user_session_to_terminate)
    else:
        print('=> An error occurred while tying to terminate sessions for the user ' + user_session_to_terminate)

    return return_code


if __name__ == "__main__":
    main()

但作为 Azure Chatbot 的一部分,当我们尝试将其插入 NodeJS 代码时,我们看到了这个问题。我的代码真的有问题吗?我应该如何正确纠正它。

我阅读了关于 python 的作用域,但在这种情况下,一切都在 main 函数内,并且知道 python try-catch 不会添加新的块作用域。所以我的期望是一切都应该奏效。请让我知道我错过了什么。

PyAutomationScript Error:Error: Command failed: C:\tcnxbot_data\automated_script\auto.exe localhost pdittaka
[9904] Failed to execute script auto
Traceback (most recent call last):
  File "auto.py", line 131, in <module>
  File "auto.py", line 118, in main
UnboundLocalError: local variable 'driver' referenced before assignment

谢谢,帕万。

标签: pythonpython-2.7

解决方案


这可能是 finally 函数内的行的问题。你本质上说的是不管是否有错误(无论是进入 try 还是 except ) execute driver.quit()

但是,如果您的代码在定义驱动程序之前或期间在 try 中遇到错误,它会进入 except,然后是您尝试关闭驱动程序的 finally。但是,这是不可能的,因为尚未定义驱动程序。你可以做的是在 main 函数的开头添加这个:

driver = None

并将内部的代码更改为finally:

if driver is not None:
   driver.quit()

推荐阅读