Python新手修改Robot Framework SeleniumLibrary遇多错误求助
Hey there! Let's walk through the issues in your code step by step—there are a few common pitfalls here that are causing those errors. Let's fix them one by one:
1. Typos and Path Handling Mistakes
- You have a typo in
DEFAULT_BROWSR—it should beDEFAULT_BROWSER(missing an 'E'). This would trigger a NameError when trying to use the default browser. - Your
DRIVERS_PATHuses backslashes (\) which act as escape characters in Python. Instead, letos.path.joinhandle path separators automatically, and skip unnecessary trailing slashes:DRIVERS_PATH = os.path.join(os.getcwd(), "drivers") - In
_get_driver_path, the linereturn getattr(self, driver_path)is incorrect.driver_pathis a string pointing to your driver executable, not an attribute of your class. Just returndriver_pathdirectly.
2. Undefined Helper Functions
You're using is_falsy() and is_truthy() which aren't built-in Python functions, and you haven't defined them in your code. Replace these with standard boolean checks:
- Swap
if is_falsy(remote_url):withif not remote_url: - Swap
if is_truthy(remote):withif remote:
3. Missing Attributes and Deprecated Methods
- In
_make_ff, you referenceself._geckodriver_log_configbut never define this attribute. Either add it to your__init__method (e.g.,self._geckodriver_log_config = {}) or remove the parameter entirely if you don't need log configuration. - The
set_headless()method for browser options is deprecated in newer Selenium versions. Use argument flags instead:- For Firefox:
options.add_argument("--headless") - For Chrome:
options.add_argument("--headless=new")(thenewflag is recommended for modern Chrome releases)
- For Firefox:
4. Incorrect Driver Path Passing
You never pass the driver executable path to webdriver.Chrome or webdriver.Firefox, so Selenium can't locate your drivers. We'll adjust the code to pass this path through all driver creation functions.
5. Confusing Browser Binary vs Driver Path
Your line desired_capabilities = {"chrome.binary": driver_path} mixes up the Chrome browser binary path with the chromedriver executable path. The driver path is passed via executable_path, while chrome.binary is only needed if you're using a non-default Chrome installation. We'll remove this hardcoded capability unless you specifically need it.
Fixed Full Code
Here's the revised code with all these fixes applied:
import os from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities DEFAULT_BROWSER = 'chrome' # Fixed typo DRIVERS_PATH = os.path.join(os.getcwd(), "drivers") # Fixed path handling BROWSER_NAMES = { 'ff': "_make_ff", 'firefox': "_make_ff", 'headlessfirefox': '_make_headless_ff', 'gc': "_make_chrome", 'googlechrome': "_make_chrome", 'headlesschrome': '_make_headless_chrome', 'chrome': "_make_chrome", } BROWSER_PATHS = { '_make_ff': os.path.join("geckodriver-win32", "geckodriver.exe"), '_make_headless_ff': os.path.join("geckodriver-win32", "geckodriver.exe"), '_make_chrome': os.path.join("chromedriver_win32", "chromedriver.exe"), '_make_headless_chrome': os.path.join("chromedriver_win32", "chromedriver.exe"), } class driver(object): """docstring for driver""" def __init__(self): self.driver = None self.driver_path = None self.timeout = 20 self.implicit_wait = 5 self._geckodriver_log_config = {} # Added missing attribute def create(self, browser_name=DEFAULT_BROWSER): return self._make_driver(browser_name) def _make_driver(self, browser_name, desired_capabilities=None, profile_dir=None, remote=None): creation_func = self._get_driver_creation_function(browser_name) driver_path = self._get_driver_path(browser_name) driver = creation_func(remote, desired_capabilities, profile_dir, driver_path=driver_path) driver.set_script_timeout(self.timeout) driver.implicitly_wait(self.implicit_wait) return driver """ Return browser function name """ def _get_driver_creation_function(self, browser_name): try: func_name = BROWSER_NAMES[browser_name.lower()] # Added case insensitivity except KeyError: raise ValueError(f"{browser_name} is not a supported browser.") return getattr(self, func_name) """ Return browser driver path """ def _get_driver_path(self, browser_name): try: func_name = self._get_driver_creation_function(browser_name) driver_path = os.path.join(DRIVERS_PATH, BROWSER_PATHS[func_name]) except KeyError: raise ValueError(f"{browser_name} is not a supported browser.") return driver_path # Fixed: return path directly """ Used inside driver creation functions """ def _generic_make_driver(self, webdriver_type, desired_cap_type, remote_url, desired_caps, driver_path, options=None): if not remote_url: if options is None: driver = webdriver_type(executable_path=driver_path) else: driver = webdriver_type(executable_path=driver_path, options=options) else: driver = self._create_remote_web_driver(desired_cap_type, remote_url, desired_caps, options=options) return driver def _create_remote_web_driver(self, capabilities_type, remote_url, desired_capabilities=None, profile=None, options=None): desired_capabilities_object = capabilities_type.copy() if not isinstance(desired_capabilities, dict): desired_capabilities = self._parse_capabilities_string(desired_capabilities) desired_capabilities_object.update(desired_capabilities or {}) return webdriver.Remote(desired_capabilities=desired_capabilities_object, command_executor=str(remote_url), browser_profile=profile, options=options) def _make_ff(self, remote, desired_capabilities, profile_dir, driver_path, options=None): if not profile_dir: profile = webdriver.FirefoxProfile() else: profile = webdriver.FirefoxProfile(profile_dir) if remote: driver = self._create_remote_web_driver(webdriver.DesiredCapabilities.FIREFOX, remote, desired_capabilities, profile, options=options) else: driver = webdriver.Firefox(firefox_profile=profile, options=options, executable_path=driver_path, **self._geckodriver_log_config) return driver def _make_headless_ff(self, remote, desired_capabilities, profile_dir, driver_path): options = webdriver.FirefoxOptions() options.add_argument("--headless") # Replaced deprecated method return self._make_ff(remote, desired_capabilities, profile_dir, driver_path, options=options) def _make_chrome(self, remote, desired_capabilities, profile_dir, driver_path, options=None): return self._generic_make_driver( webdriver.Chrome, webdriver.DesiredCapabilities.CHROME, remote, desired_capabilities, driver_path, options=options) def _make_headless_chrome(self, remote, desired_capabilities, profile_dir, driver_path): options = webdriver.ChromeOptions() options.add_argument("--headless=new") # Replaced deprecated method return self._make_chrome(remote, desired_capabilities, profile_dir, driver_path, options) # Added missing method called in remote driver creation def _parse_capabilities_string(self, capabilities_str): # Implement custom parsing logic here if needed; returns empty dict for now return {}
Key Extra Improvements:
- Added
.lower()tobrowser_namein_get_driver_creation_functionfor case-insensitive browser name handling (e.g., "Chrome" vs "chrome") - Added the missing
_parse_capabilities_stringmethod (it was called but never defined) - Passed
driver_pathas a parameter to all driver creation functions so they can use it withexecutable_path - Fixed Firefox driver creation to include the executable path
Now when you run driver().create(), it should correctly locate your chromedriver executable and launch Chrome as expected.
内容的提问来源于stack exchange,提问作者deyaamuhammad

