重写 AppiumService 类,添加默认启动参数,并实时显示启动日志

news2025/1/25 9:13:01

一、前置说明

在Appium的1.6.0版本中引入了AppiumService类,可以很方便的通过该类来管理Appium服务器的启动和停止。经过测试,使用该类的实例执行关闭server时,并没有释放端口号,会导致第二次启动时失败。另外,使用该类启动server,不能在窗口中实时显示日志,不方便调试。因此,可以重写 AppiumService 类的 start 方法和 stop 方法,实现相应功能。

二、代码实现

import logging

from appium.webdriver.appium_service import *
from appium.webdriver.appium_service import AppiumService as OriginalServer

from libs import path, file_util
from libs.cmd_util import cmd_executor as cmd

logger = logging.getLogger(__name__)


class AppiumService(OriginalServer):

    def __init__(self, port=4723, log_file_path=None, tail_log=False):
        super().__init__()

        self.port = port
        self.log_file_path = log_file_path

        # 用于控制是否开启cmd窗口,实时展示日志内容,当调试代码时建议开启
        self.tail_log = tail_log

        if not self.log_file_path:
            self.log_file_path = os.path.join(path.get_log_dir(), f'appium_server_{port}.log')

        if os.path.exists(self.log_file_path):
            os.remove(self.log_file_path)

        self.default_start_args = ['-p', str(self.port),
                                   '-g', self.log_file_path,
                                   '--session-override',
                                   '--log-timestamp',
                                   '--session-override',
                                   '--local-timezone',
                                   '--allow-insecure',
                                   'chromedriver_autodownload'
                                   ]

    def start(self, **kwargs: Any) -> sp.Popen:
        self.stop()

        env = kwargs['env'] if 'env' in kwargs else None
        node: str = kwargs.get('node') or get_node()
        npm: str = kwargs.get('npm') or get_npm()
        main_script: str = kwargs.get('main_script') or get_main_script(node, npm)
        # A workaround for https://github.com/appium/python-client/issues/534
        default_std = sp.DEVNULL if sys.platform == 'win32' else sp.PIPE
        stdout = kwargs['stdout'] if 'stdout' in kwargs else default_std
        stderr = kwargs['stderr'] if 'stderr' in kwargs else default_std
        timeout_ms = int(kwargs['timeout_ms']) if 'timeout_ms' in kwargs else STARTUP_TIMEOUT_MS
        args: List[str] = [node, main_script]
        if 'args' in kwargs:
            args.extend(kwargs['args'])

        # ==================添加这段逻辑(开始):设置默认启动参数=======================
        if self.port:
            args.extend(self.default_start_args)
        # ==================添加这段逻辑(结束):设置默认启动参数=======================

        self._cmd = args
        self._process = sp.Popen(args=args, stdout=stdout, stderr=stderr, env=env)

        error_msg: Optional[str] = None
        startup_failure_msg = (
            'Appium server process is unable to start. Make sure proper values have been '
            f'provided to \'node\' ({node}), \'npm\' ({npm}) and \'main_script\' ({main_script}) '
            f'method arguments.'
        )
        if timeout_ms > 0:
            status_url_path = make_status_url(args)
            try:
                if not self._poll_status(parse_host(args), parse_port(args), status_url_path, timeout_ms):
                    error_msg = (
                        f'Appium server has started but is not listening on {status_url_path} '
                        f'within {timeout_ms}ms timeout. Make sure proper values have been provided '
                        f'to --base-path, --address and --port process arguments.'
                    )
            except AppiumStartupError:
                error_msg = startup_failure_msg
        elif not self.is_running:
            error_msg = startup_failure_msg
        if error_msg is not None:
            if stderr == sp.PIPE and self._process.stderr is not None:
                err_output = self._process.stderr.read()
                if err_output:
                    error_msg += f'\nOriginal error: {str(err_output)}'
            self.stop()
            raise AppiumServiceError(error_msg)

        # ==================添加这段逻辑(开始):是否启动cmd窗口跟踪log日志=======================
        if self.tail_log:
            file_util.tail_log_file(self.log_file_path)
        # ==================添加这段逻辑(结束):是否启动cmd窗口跟踪log日志=======================

        return self._process

    def stop(self) -> bool:
        status = super().stop()

        # 经过实测,原stop()方法执行之后,进程仍被占用,所以这里添加一个关闭进程的逻辑
        cmd.kill_process_by_port(self.port)

        return status


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    service = AppiumService(port=4723, tail_log=True)
    service.start()

三、Demo验证

执行代码,顺利启动appium server,并启动了一个命令行窗口,实时展示了server的日志。

欢迎技术交流:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1297631.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

9.基于SpringBoot3+I18N实现国际化

1. 新建资源文件 在resources目录下新建目录i18n, 然后 新建messages_en.properties文件 user.login.erroraccount or password error!新建messages_zh_CN.properties文件 user.login.error帐户或密码错误!2. 新建LocaleConfig.java文件 Configurati…

geolife笔记:整理处理单条轨迹

以 数据集笔记 geolife (操作篇)_geolife数据集-CSDN博客 轨迹为例 1 读取数据 import pandas as pd data pd.read_csv(Geolife Trajectories 1.3/Data//000/Trajectory/20081023025304.plt,headerNone, skiprows6,names[Latitude, Longitude, Not_Im…

手持式安卓主板_PDA安卓板_智能手持终端方案

手持式安卓主板方案是一种智能终端设备,具备自动对焦和闪光灯功能,可以在昏暗的环境下快速扫描二维码并轻松采集数据。该方案还提供多渠道支付和数据采集功能,为用户提供了便捷的体验。 该方案的产品基于手持式安卓主板,并搭载了八…

如何提高Pycharm的使用体验?

汉化 文件---设置---插件---chinese---安装---重启ide 代码补全 tabnine 文件---设置---插件---tabnine---安装---重启ide 重启ide后生效,补全效果如下 自定义背景 文件---设置---外观---背景图像---选择图片---调整透明度保存即可 设置头部声明 英文版…

JVM学习笔记-如何在IDEA打印JVM的GC日志信息

若要在Idea上打印JVM相应GC日志,其实只需在Run/Debug Configurations上进行设置即可。 拿《深入Java虚拟机》书中的3-7代码例子来演示,如 1 public class JvmTest {2 private static final int _1MB1024*1024;3 public static void main(String…

理解基于 Hadoop 生态的大数据技术架构

转眼间,一年又悄然而逝,时光荏苒,岁月如梭。当回首这段光阴,不禁感叹时间的匆匆,仿佛只是一个眨眼的瞬间,一年的旅程已成为过去,而如今又到了画饼的时刻了 ! 基于 Hadoop 生态的大数…

快速认识什么是:Docker

Docker,一种可以将软件打包到容器中并在任何环境中可靠运行的工具。但什么是容器以及为什么需要容器呢?今天就来一起学快速入门一下Docker吧!希望本文对您有所帮助。 假设您使用 Cobol 构建了一个在某种奇怪风格的 Linux 上运行的应用程序。您…

Spring Boot Async:从入门到精通,原理详解与最佳实践

Spring Boot 的异步功能(Async)允许我们将某些任务异步执行,而不会阻塞主线程。这对于处理耗时的操作非常有用,如发送电子邮件、生成报表、调用外部 API 等。通过异步处理,我们可以释放主线程,让它继续处理…

【学习笔记】lyndon分解

摘抄自quack的ppt。 这部分和 s a sa sa的关联比较大,可以加深对 s a sa sa的理解。 Part 1 如果字符串 s s s的字典序在 s s s以及 s s s的所有后缀中是最小的,则称 s s s是一个 lyndon \text{lyndon} lyndon串。 lyndon \text{lyndon} lyndon分解&a…

连接Redis报错解决方案

连接Redis报错&解决方案 问题描述:Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝,无法连接。 问题原因:redis启动方式不正确 解决方案: 在redis根目录下打开命令行窗口,输入命令redi…

【SpringBoot】分层解耦

1. 三层架构 Controller:控制层。接收前端发送的请求,调用Service层来进行逻辑处理(Service层处理完后,把处理结果返回给Controller层)Service:业务逻辑层。处理具体的业务逻辑。调用Dao层(逻辑…

旺店通无代码API集成:电商平台的客服系统和营销自动化解决方案

无代码API集成的力量 在数字化转型的浪潮中,电商平台迅速崛起,成为企业不可或缺的销售和市场推广渠道。旺店通企业版奇门以其无代码开发的连接和集成能力,重塑了电商系统的运营模式。无需繁琐的API开发,企业即可实现电商平台与客…

AI:95-基于卷积神经网络的艺术品风格分类

🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的核心代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在不断更新…

第一课【习题】HarmonyOS应用/元服务上架

元服务发布的国家与地区仅限于“中国大陆” 编译打包的软件包存放在项目目录build > outputs > default下 创建应用时,应用包名需要和app.json5或者config.json文件中哪个字段保持一致? 发布应用时需要创建证书,证书类型选择什么…

csdn调整样式之居中、空格、换行、字体字号、自动生成目录

文章目录 1、居中2、空格3、换行4、字体字号5、[TOC](文章目录) 自动生成目录6、列表7、分割线8、引用代码 1、居中 <center>文字居中 2、空格 一个空格   &emsp;三个空格一个空格    三个空格 3、换行 <br>你好 4、字体字号 <font color red size…

# K近邻算法 度量距离

K近邻算法 度量距离 欧氏距离(Euclidean distance) 欧几里得度量(euclidean metric)(也称欧氏距离)是一个通常采用的距离定义&#xff0c;指在 m m m维空间中两个点之间的真实距离&#xff0c;或者向量的自然长度(即该点到原点的距离)。在二维和三维空间中的欧氏距离就是两点…

Kubernetes创始人发声!K8s 变得太复杂了

关注【云原生百宝箱】公众号&#xff0c;获取更多云原生消息 Kubernetes 变得太复杂了&#xff0c;它需要学会克制&#xff0c;否则就会停止创新&#xff0c;直至丢失大本营。 Kubernetes 联合创始人Tim Hockin 罕见发声。在今年的 KubeCon 上&#xff0c;他建议&#xff0c;K…

【Altera】Quartus II 软件怎么更改bank电压

前言 FPGA的bank电压要和物理设计相同&#xff0c;Quartus II 软件怎么更改bank电压&#xff1f; 步骤 启动 Pin Planner&#xff08;快捷方式&#xff1a;CTRL Shift N&#xff09;右键单击 Pin Planner 的背景&#xff0c;然后选择"显示 I/O bank"。右键…

学习git后,真正在项目中如何使用?

文章目录 前言下载和安装Git克隆远程仓库PyCharm链接本地Git创建分支修改项目工程并提交到本地仓库推送到远程仓库小结 前言 网上学习git的教程&#xff0c;甚至还有很多可视化很好的git教程&#xff0c;入门git也不是什么难事。但我发现&#xff0c;当我真的要从网上克隆一个…

Vue:Vue的开发者工具不显示Vue实例中的data数据

一、情况描述 代码&#xff1a; 页面&#xff1a; 可以看到&#xff0c;input获取到了data数据&#xff0c;但是&#xff0c;vue-devtool没有获取到data数据 二、解决办法 解决办法1&#xff1a; data.name的值不能全是中文&#xff0c;比如改成aa尚硅谷 解决办法2&…