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

一、前置说明

在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的日志。

欢迎技术交流:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是MyBatis、什么是MyBatis-Plus、简单详细上手案例

什么是MyBatis MyBatis是一个开源的Java持久层框架,用于简化与关系型数据库的交互。它通过将SQL语句与Java代码进行分离,提供了一种优雅的方式来处理数据库操作。 MyBatis的核心思想是将SQL语句与Java方法进行映射,使得开发人员可以通过配置…

Java LeetCode篇-深入了解二叉树的经典解法(多种方式实现:构造二叉树)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 从前序与中序遍历序列来构造二叉树 1.1 实现从前序与中序遍历序列来构造二叉树思路 1.2 代码实现从前序与中序遍历序列来构造二叉树 2.0 从中序与后序遍历序…

实用篇 | 一文学会人工智能中API的Flask编写(内含模板)

----------------------- 🎈API 相关直达 🎈-------------------------- 🚀Gradio: 实用篇 | 关于Gradio快速构建人工智能模型实现界面,你想知道的都在这里-CSDN博客 🚀Streamlit :实用篇 | 一文快速构建人工智能前端展…

【优选算法系列】【专题二滑动窗口】第三节.904. 水果成篮和438. 找到字符串中所有字母异位词

文章目录 前言一、水果成篮 1.1 题目描述 1.2 题目解析 1.2.1 算法原理 1.2.2 代码编写 1.2.3 题目总结二、找到字符串中所有字母异位词 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 2.2.2 代码编写 …

OpenAI 首席运营官(COO)Brad Lightcap认为商业人工智能被夸大了

美国消费者新闻与商业频道(CNBC)是美国NBC环球集团持有的全球性财经有线电视卫星新闻台,是全球财经媒体中的佼佼者,其深入的分析和实时报导赢得了全球企业界的信任。在1991年前,使用消费者新闻与商业频道(C…

node.js和npm的安装与环境配置(2023最新版)

目录 安装node.js测试是否安装成功测试npm环境配置更改环境变量新建系统变量 安装node.js 1、进入官网下载:node.js官网 我选择的是windows64位的,你可以根据自己的实际情况选择对应的版本。 2、下载完成,安装。 打开安装程序 接受协议 选…

链表OJ—环形链表的约瑟夫问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 世上有两种耀眼的光芒,一种是正在升起的太阳,一种是正在努力学习编程的你!一个爱学编程的人。各位看官,我衷心的希望这篇博客能对你…

操作系统———磁盘调度算法模拟

实验目的 磁盘是可供多个进程共享的设备,当有多个进程都要求访问磁盘是,应采用一种最佳调度算法,以使各进程对磁盘的平均访问时间最小。目前最成用的磁盘调度算法有先来先服务(FCFS),最短寻道时间优先&…

增加网站流量的方法

如果您的网站没有获得足够的流量,您可能会错过在线发展业务的重要机会。搜索引擎优化(SEO)可以帮助提高您网站的知名度,从而吸引更多客户。 SEO的重点是识别高价值的关键词,并将它们整合到网站的内容中,使…

【设计模式-3.2】结构型——适配器模式

说明:本文介绍设计模式中结构型设计模式中的,适配器模式; 插头转换器 适配器模式属于结构型设计模式,设计思想体现在结构上的。以插头转换器为例,当你需要给手机充电,但是眼前只有一个三孔插座&#xff0…

MES管理系统在非标制造企业中的应用

在当今制造业中,非标制造企业逐渐成为一种重要的存在。与传统的批量生产制造企业不同,非标制造企业主要特点是能够根据客户需求进行定制化生产。这种定制化的生产模式对企业的管理提出了更高的要求,同时也带来了更多的挑战。在非标制造企业中…

Emacs之Plantuml用于复杂UML类图(Markdown用于简单类图)(一百三十二)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

MQTT主题、通配符和最佳实践

MQTT主题在MQTT生态系统非常重要,因为代理(broker)依赖主题确定哪个客户端接收指定的主题。本文我们将聚集MQTT主题、MQTT通配符,详细讨论使用它们的最佳实践,也会探究SYS主题,提供给代理(broke…

超越极限!如何进行高效分布式性能测试,让Jmeter揭示并发下系统的真正实力

一、为什么要进行分布式性能测试 当进行高并发性能测试的时候,受限于Jmeter工具本身和电脑硬件的原因,无法满足我们对大并发性能测试的要求。 基于这种场景下,我们就需要采用分布式的方式来实现我们高并发的性能测试要求。 二、分布式性能测…

深度学习记录--激活函数

激活函数的种类 对于激活函数的选择,通常有以下几种 sigmoid,tanh,ReLU,leaky ReLU 激活函数的选择 之前logistic回归一直使用的激活函数都是sigmoid函数,但一般来说,tanh函数是比sigmoid函数更加好的选…

【小白专用】在 vs 中使用 nuget 安装NPOI

C#操作Excel有多种方法,如通过数据库的方式来读写Excel的OleDb方式,但是OleDb方式需要安装微软office,还可以通过COM组件方式操作Excel,也需要安装微软Excel。如果不想安装微软办公套餐可以使用ClosedXML、EPPlus、NPOI。本文主要…

理解IoC容器初始化

问题:当自己面试或者背诵八股文时,会背到各种各样的spring底层的东西,自己越看越迷糊。 OS:不知道兄弟们是不是也会这样?如果大家没有说明我太菜了。 原因:就是自己学的框架越来越多,很多框架…

线性回归实战

3.1 使用正规方程进行求解 3.1.1 简单线性回归 公式 : y w x b y wx b ywxb 一元一次方程,在机器学习中一元表示一个特征,b表示截距,y表示目标值。 使用代码进行实现: 导入包 import numpy as np import matp…

bc-linux-欧拉重制root密码

最近需要重新安装虚拟机的系统 安装之后发现对方提供的root密码不对,无法进入系统。 上网搜了下发现可以进入单用户模式进行密码修改从而重置root用户密码。 在这个界面下按e键 找到图中部分,把标红的部分删除掉,然后写上rw init/bin/…

JAVEE初阶 多线程基础(七)

懒汉模式 指令重排序问题 一. 懒汉模式的意义和代码实现二. 饿汉模式和懒汉模式的线程安全三. 懒汉模式的线程安全问题解决3.1 加锁阶段3.2 嵌套if阶段3.3 指令重排序问题3.4 解决线程安全问题阶段 一. 懒汉模式的意义和代码实现 在上一章节中,我们先学习了单例模式中的饿汉模式…