启动多个Appium服务
Appium常用参数
参数 | 默认值 | 含义 | |
---|---|---|---|
-u, --udid | null | 连接设备的唯一设备标识符 | |
-a, --address | 0.0.0.0 | 监听的ip地址 | |
-p, --port | 4723 | 监听的端口 ,(设置监听端口号时最好间隔一位设置,例如设置下一个端口号设置为4725) | |
-bp, --bootstrap-port | 4724 | 连接Android设备的端口号(Android-only)(设备端口号与监听端口号相隔一位) | |
-g, --log | null | 将日志输出到指定文件 | |
–no-reset | false | session之间不重置应用状态 | |
–session-override | false | 允许session被覆盖(冲突的话) | |
–app-activity | null | 打开Android应用时,启动的Activity(Android-only)的名字 | |
–app | null | 本地绝对路径或http URL所指向的一个安装包 |
更多参数可以输入命令(CMD):appium -h
启动两个appium服务案例
启动第一个appium服务
C:\Users\Administrator>appium -p 4723
[Appium] Welcome to Appium v1.16.0
[Appium] Appium REST http interface listener started on 0.0.0.0:4723
启动第二个appium服务
C:\Users\Administrator>appium -p 4725
[Appium] Welcome to Appium v1.16.0
[Appium] Non-default server args:
[Appium] port: 4725
[Appium] Appium REST http interface listener started on 0.0.0.0:4725
Appium安卓手机每次运行时都要安装Unlock、Setting解决方案
首先通过如下命令找到appium的安装路径
C:\Users\Administrator>where appium
C:\Users\Administrator\AppData\Roaming\npm\appium
C:\Users\Administrator\AppData\Roaming\npm\appium.cmd
1、打开,并修改以下内容(最好用Notepad++打开)
路径根据上面appium存放文件夹(C:\Users\Shuqing\AppData\Roaming\npm)下继续打开以下相应文件夹
\node_modules\appium\node_modules\appium-android-driver\lib 中的android-helpers.js
修改以下内容(ctrl+g,跳转行快捷键)
#注释475行如下代码(两个斜杠“//”即为注释代码)
//await helpers.pushSettingsApp(adb);
#注释486行如下代码
//await helpers.pushUnlock(adb);
2.打开C:\Users\Shuqing\AppData\Roaming\npm\node_modules\appium\node_modules\appium-android-driver\build\lib中的android-helpers.js
修改如下内容
#注释1128行下面这行代码
//return _regeneratorRuntime.awrap(helpers.pushSettingsApp(adb));
#修改为如下:return context$1$0.abrupt('return', defaultIME);
#注释1163行下面这行代码
//return _regeneratorRuntime.awrap(helpers.pushUnlock(adb));
#修改如下:return context$1$0.abrupt('return', defaultIME);
修改完成后重启Appium服务即可,如果新设备没有这个两个守护App可以手动安装这两个App到设备。
Appium Setting路径 :
{appium安装路径}\node_modules\_io.appium.settings@2.4.0@io.appium.settings\app\build\outputs\apk\settings_apk-debug.apk
Unlock app路径:
appium安装路径\node_modules\_appium-unlock@2.0.0@appium-unlock\bin \unlock_apk-debug.apk
启动多台设备
from appium import webdriver
import yaml
from time import ctime
with open("../option_files/Yaml_info.yaml", 'r') as file:
data = yaml.load(file,Loader=yaml.FullLoader)
def appium_desire(udid,port):
desired_caps = {}
desired_caps['platformName'] = data['platformName']
desired_caps['platformVersion'] = data['platformVersion']
desired_caps['deviceName'] = data['deviceName']
desired_caps[udid] = udid
desired_caps['app'] = data['app']
desired_caps['noReset'] = data['noReset']
desired_caps['appPackage'] = data['appPackage']
desired_caps['appActivity'] = data['appActivity']
print('appium port:{0} start run devices:{1} at {2}'.format(port, udid, ctime()))
webdr = webdriver.Remote('http://{0}:{1}/wd/hub'.format(data['ip'],str(port)),desired_caps)
return webdr
if __name__ == '__main__':
devices_list = ['127.0.0.1:21503', '127.0.0.1:21513'] #需启动的设备列表
appium_desire(devices_list[0], 4723)
appium_desire(devices_list[1], 4725)
capbility配置文件(Yaml_info.yaml)
platformName: Android
platformVersion: 5.1.1
#deviceName: 127.0.0.1:62001
deviceName: 127.0.0.1:21503
#app: D:\Documents\Downloads\com.baidu.BaiduMap.apk
app: D:\Documents\Downloads\com.tencent.mm-7.0.4.apk
noReset: False
#noReset: True
#appPackage: com.baidu.BaiduMap
appPackage: com.tencent.mm
#appActivity: com.baidu.baidumaps.WelcomeScreen
appActivity: com.tencent.mm.ui.LauncherUI
unicodeKeyboard: True
resetKeyboard: True
ip: 127.0.0.1
多进程并发启动设备
from appium import webdriver
import yaml
from time import ctime
import multiprocessing
devices_list = ['127.0.0.1:21503', '127.0.0.1:21513']
with open("../option_files/Yaml_info.yaml", 'r') as file:
data = yaml.load(file,Loader=yaml.FullLoader)
def appium_desire(udid,port):
desired_caps = {}
desired_caps['platformName'] = data['platformName']
desired_caps['platformVersion'] = data['platformVersion']
desired_caps['deviceName'] = data['deviceName']
desired_caps[udid] = udid
desired_caps['app'] = data['app']
desired_caps['noReset'] = data['noReset']
desired_caps['appPackage'] = data['appPackage']
desired_caps['appActivity'] = data['appActivity']
print('appium port:{0} start run devices:{1} at {2}'.format(port, udid, ctime()))
webdr = webdriver.Remote('http://{0}:{1}/wd/hub'.format(data['ip'],str(port)),desired_caps)
return webdr
# 构造设备进程组
desired_process = []
# 加载进程
for i in range(len(devices_list)):
port = 4723+2*i
desired = multiprocessing.Process(target=appium_desire, args=(devices_list[i],port))
desired_process.append(desired)
if __name__ == '__main__':
# 并发启动多台设备
for desired in desired_process:
desired.start()
for desired in desired_process:
desired.join()
Python启动Appium服务
Python启动Appium服务需要使用subprocess模块,该模块可以创建新的进程,并且连接
到进程的输入、输出、错误等广岛信息,并且可以扩区进程的返回值。
subprocess模块官方文档
subprocess.Popen参数参考
启动单个Appium服务
import subprocess
from time import ctime
def appium_start(host,port):
'''启动appium server'''
bootstrap_port = str(port+1)
cmd = "start /b appium -a "+host+' -p '+str(port)+' -bp '+ str(bootstrap_port) # 其中参数/b 是将cmd窗口指定为后台运行不弹出
print('{0} at {1}'.format(cmd,ctime()))
subprocess.Popen(cmd, shell=True, stdout=open('../appium_log/'+str(port)+'.log','a'), stderr=subprocess.STDOUT)
if __name__ == '__main__':
host = "127.0.0.1"
port = 4725
appium_start(host,port)
启动校验
启动后我们需要校验服务是否启动成功,校验方法如下:
- 首先查看有没有生成对应的log文件,查看log里面的内容。
- 使用如下命令来查看
netstat -ano |findstr 端口号
注:netstat 命令解释
netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。输入 netstat -ano 回车.可以查看本机开放的全部端口;输入命令 netstat -h可以查看全部参数含义。
关闭Appium服务
关闭进程有2种方式,具体如下:
- 通过netstat命令找到对应的Appium进程pid然后可以在系统任务管理器去关闭进程;
- 使用如下命令来关闭:
taskkill -f -pid appium进程id
多个appium服务启动
import subprocess
from time import ctime
def appium_start(host,port):
'''启动appium server'''
bootstrap_port = str(port+1)
cmd = "start /b appium -a "+host+' -p '+str(port)+' -bp '+ str(bootstrap_port) # 其中参数/b 是将cmd窗口指定为后台运行不弹出
print('{0} at {1}'.format(cmd,ctime()))
subprocess.Popen(cmd, shell=True, stdout=open('../appium_log/'+str(port)+'.log','a'), stderr=subprocess.STDOUT)
if __name__ == '__main__':
host = "127.0.0.1"
for i in range(2):
port = 4723+i*2
appium_start(host,port)
多进程并发启动appium服务
import subprocess
from time import ctime
from multiprocessing import Process
def appium_start(host,port):
'''启动appium server'''
bootstrap_port = str(port+1)
cmd = "start /b appium -a "+host+' -p '+str(port)+' -bp '+ str(bootstrap_port) # 其中参数/b 是将cmd窗口指定为后台运行不弹出
print('{0} at {1}'.format(cmd,ctime()))
subprocess.Popen(cmd, shell=True, stdout=open('../appium_log/'+str(port)+'.log','a'), stderr=subprocess.STDOUT)
# 构建appium进程
appium_process = []
# 加载appium进程
for i in range(2):
host = '127.0.0.1'
port = 4723 +2*i
appium = Process(target=appium_start, args=(host,port))
appium_process.append(appium)
if __name__ == '__main__':
for appium in appium_process:
appium.start()
for appium in appium_process:
appium.join()
Appium 端口检测
端口检测
端口检测需要使用到socket模块来校验端口是否被占用。
python socket模块官方文档
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。
import socket
def check_port(host, port):
'''检查指定的端口是否被占用'''
# 创建socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET 是以IPV4协议进行通讯
try:
s.connect((host,port))
s.shutdown(2)
except OSError as msg:
print('prort {0} is available!'.format(port))
print(msg)
return True
else:
print('port {0} already be in use!'.format(port))
return False
if __name__ == '__main__':
host = '127.0.0.1'
port = 4723
check_port(host,port)
方法:shutdown(self, flag):
禁止在一个Socket上进行数据的接收与发送。利用shutdown()函数使socket双向数据传输变为单向数据传输。shutdown()需要一个单独的参数, 该参数表示了如何关闭socket参数
· 0表示禁止将来读;
· 1表示禁止将来写
· 2表示禁止将来读和写。
当端口可以使用时,控制台输出如下:此使说明服务端没有开启这个端口服务,所以可用。
端口释放
import os
def release_port(port):
'''释放指定的端口'''
# 查找对应端口号的pid
cmd_find = 'netstat -aon | findstr {}'.format(port)
print(cmd_find)
# 返回对应端口的pid
result = os.popen(cmd_find).read()
print(result)
if str(port) and 'LISTENING' in result:
# 获取端口对应的pid进程
i = result.index('LISTENING')
start = i+len('LISTENING')+7
end = result.index('\n')
pid = result[start:end]
# 关闭被占用端口的pid
cmd_kill = 'taskkill -f -pid {0}'.format(pid)
print(cmd_kill)
os.popen(cmd_kill)
else:
print('port {0} is available!'.format(port))
if __name__ == '__main__':
host = '127.0.0.1'
port = 4723
release_port(port)