1. 程式人生 > 實用技巧 >app自動化11 執行緒實現多個指令碼在多個手機執行

app自動化11 執行緒實現多個指令碼在多個手機執行

執行緒

多工簡單介紹

- 有很多事情在現實生活的場景中是同時進行的,比如開車的時候 手和腳共同來駕駛汽車,再比如唱歌跳舞也是同時進行的。- 多工,就是能夠在同一時間同時進行多個任務。這樣同時進行多個任務,有一個極大的好處,那就是節省時間程式碼舉例
import time
import threading

def sing():
    for i in range(5):
        print("唱歌")
        time.sleep(1)

def dance():
    for i in range(5):
        print("跳舞")
        time.sleep(1)

t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)

t1.start()
t2.start()
import time
import threading

def sing():
    for i in range(5):
        print("唱歌")
        time.sleep(1)

def dance():
    for i in range(5):
        print("跳舞")
        time.sleep(1)

sing()
dance()
第一段程式碼開啟3個執行緒,分別是主執行緒,子執行緒t1,子執行緒t2,耗時一共是5秒第二段程式碼開啟1個執行緒,那就是主執行緒,耗時一共是10秒
為什麼第一段程式碼耗時只要5秒,而第二段程式碼耗時要10秒呢?

下面就由sunt來為大家說下原因吧,先分析第一段程式碼:
主執行緒先開始執行,然後讓兩個小弟,也就是子執行緒t1,t2。分別去執行sing()和dance()程式碼,這兩個小弟是並行執行的,並不是說小弟t1先執行完,小弟t2才去執行,而是兩個小弟同時執行,故耗時為5秒,圖解如下:打印出來結果:
唱歌
跳舞
跳舞
唱歌
跳舞
唱歌
跳舞
唱歌
跳舞
唱歌
這是因為當他們從休眠到喚醒是同時的,故資源掠奪的不確定性,有可能跳舞先執行,也有可能唱歌先執行,不過一定是成對出現的。並行執行耗時總時間為5秒。
接下來分析第二段程式碼:主執行緒先開始執行,然後主執行緒執行sing()程式碼塊,等待sing()程式碼塊執行完之後,才開始執行dance()程式碼塊。故耗時為sing()程式碼塊的時間加dance()程式碼塊的時間,一共為10秒。圖解如下:

多工的原理

什麼叫“多工”呢?簡單地說,就是作業系統可以同時執行多個任務。打個比方,你一邊在用瀏覽器上網,一邊在聽MP3,一邊在用Word趕作業,這就是多工,至少同時有3個任務正在執行。還有很多工悄悄地在後臺同時執行著,只是桌面上沒有顯示而已。單核cpu工作原理- 現在,多核CPU已經非常普及了,但是,即使過去的單核CPU,也可以執行多工。由於CPU執行程式碼都是順序執行的,那麼,單核CPU是怎麼執行多工的呢?- 答案就是作業系統輪流讓各個任務交替執行,任務1執行0.01秒,切換到任務2,任務2執行0.01秒,再切換到任務3,執行0.01秒……這樣反覆執行下去。實際上看,每個任務都是交替執行的,但是,由於CPU的執行速度實在是太快了,我們感覺就像所有任務都在同時執行一樣。- 真正的並行執行多工只能在多核CPU上實現,但是,由於任務數量遠遠多於CPU的核心數量,所以,作業系統也會自動把很多工輪流排程到每個核心上執行。多核cpu工作原理和單核類似,相當於多了一個幹活的人。併發:指的是任務數多於cpu核數,通過作業系統的各種任務排程演算法,實現用多個任務“一起”執行(實際上總有一些任務不在執行,因為切換任務的速度相當快,看上去一起執行而已)並行:指的是任務數小於等於cpu核數,即任務真的是一起執行的- 並行和併發都算是多工,但並行實際上才是真正的多工,併發是假的。

執行緒的兩張建立方式

- 直接使用threading模組的Thread類,指定要執行的方法,再呼叫start- 使用繼承的方式,繼承Thread類,重新run方法,建立這個物件後,再呼叫start

檢視當前程式執行緒數量

threading.enumerate()- 獲取所有執行緒,返回的是一個列表。
- 如果需要個數,使用len(threading.enumerate())

為子執行緒傳遞引數

target方式
import time
import threading 

def sing(nums):
    for i in range(nums):
        print("唱歌")
        time.sleep(1)

def dance():
    for i in range(5):
        print("跳舞")
        time.sleep(1)

t1 = threading.Thread(target=sing, args=(3,))
t2 = threading.Thread(target=dance)

t1.start()
t2.start()
類繼承方式
import threading

class Work1(threading.Thread):

    def __init__(self, nums):
        super().__init__()
        self.nums = nums

    def run(self):
        for i in range(self.nums):
            print("haha")


def main():
    w = Work1(2)
    w.start()

if __name__ == "__main__":
    main()

Appium多埠

目標,讓一個指令碼去跑到多臺手機。注意點: appium sever埠要不同,開啟多個。bootstrap埠要不同,開啟多個。udid需要指定,udid表示裝置的唯一表示符號,通過 adb devices 檢視。 前半部分都是,比如模擬器的(192.168.57.101:5555)。
appium server 和 bootstrap 和 udid 應該是成對出現的。
命令:
appium -p 4723 -bp 4724 -U 192.168.57.101:5555
-p 表示 appium的埠-bp 表示 bootstrap的埠
-U 表示裝置的識別符號
修改init_driver讓,init_driver接受port的引數。並且進行對應的連線。
記得,建立的是不同的driver物件。
因為如果使用threading.Thread的這種形式,需要指定執行的函式,所以,把需要執行的程式碼,封裝成一個函式。然後使用
    ports = ["4723", "4725"]

    for i in ports:
        threading.Thread(target=do, args=(i,)).start()
來去執行建立多個driver並且進行指令碼的操作。下面看圖解就知道appium多埠的工作原理了。依照上圖可以知道,如果要想讓一段指令碼操作兩個手機,那麼我要做的就是,開啟兩個appium服務和兩個bootstrap服務,並且埠號不能相同,appium和bootstrap是一對,並且有兩個手機,還要指定手機裝置號,故命令如下
appium -p 4723 -bp 4724 -U 192.168.57.101:5555
    
appium -p 4725 -bp 4726 -U 192.168.57.102:5555

程式碼實現

命令列先啟動appium並指定埠,並指定bootstrap埠和手機裝置號
appium -p 4723 -bp 4724 -U 192.168.57.101:5555
    
appium -p 4725 -bp 4726 -U 192.168.57.102:5555
base_driver.py
from appium import webdriver


def init_driver(port="4723"):
    # server 啟動引數
    desired_caps = dict()
    # 裝置資訊
    desired_caps['platformName'] = 'Android'
    desired_caps['platformVersion'] = '5.1'
    desired_caps['deviceName'] = '192.168.164.101:5555'
    # app資訊
    desired_caps['appPackage'] = 'com.android.settings'
    desired_caps['appActivity'] = '.Settings'
    # 中文
    desired_caps['unicodeKeyboard'] = True
    desired_caps['resetKeyboard'] = True
    # 不重置應用
    desired_caps['noReset'] = True
    # toast
    # desired_caps['automationName'] = 'Uiautomator2'
    # 宣告物件
    driver = webdriver.Remote('http://localhost:' + port + '/wd/hub', desired_caps)
    return driver
login_page.py
from base_action import BaseAction


class LoginPage(BaseAction):

    pass
demo.py
import threading

from selenium.webdriver.common.by import By

from base_driver import init_driver
from base_action import BaseAction
from login_page import LoginPage


def do(port):
    driver = init_driver(port)
    login_page = LoginPage(driver)
    if "4723" == port:
        login_page.click((By.XPATH, "text,更多"))
    else:
        login_page.click((By.XPATH, "text,WLA"))

def main():
    //根據ports不同,driver可以連線不同的手機
    ports = ["4723", "4725"]

    for i in ports:
        threading.Thread(target=do, args=(i,)).start()

if __name__ == '__main__':
    main()