在我的Python環(huán)境(Win7+Python2.7.9)下測試沒問題,是等待5秒后再輸出 m。
創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的牡丹網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
你的問題可能是被標(biāo)準輸出流的緩沖區(qū)緩沖了,給 stdout 加一個 flush 就可以了:
from?time?import?sleep
from?sys?import?stdout
print?"s"
stdout.flush()
sleep(5)
print?"m"
年前走查腳本代碼時,發(fā)現(xiàn)大家對selenium功能都在重復(fù)造輪子,而且容易出現(xiàn)一些常見低級bug。于是在閑暇之余,封裝一些常用的selenium功能。
在某些網(wǎng)頁中,存在多個frame嵌套。而selenium提供的find_element函數(shù)只能在當(dāng)前frame中查找,不能切換到其他frame中,需要從最上級frame中逐步切換(當(dāng)然也可以指定xpath的絕對路徑,但是一般沒人這么做)。在我們寫代碼過程中,需要明確知道當(dāng)前frame位置和需要尋找元素的frame位置。在frame切換過程中,容易因為疏忽導(dǎo)致frame切換錯誤導(dǎo)致元素?zé)o法找到的bug。
頁面中分布的frame,可以理解為樹狀結(jié)構(gòu)。因此我們可以采用遞歸的方式, 沿著某條搜索路線frame節(jié)點,依次對樹中每個節(jié)點均做一次訪問。
我們以163網(wǎng)址上的登錄框為例:點擊登錄按鈕,彈出登錄iframe頁面。輸入框位置在iframe中,因此我們不能使用xpath獲取元素位置,需要進入iframe中,然后獲取元素。
手動切換ifame可能會產(chǎn)生bug,因此需要一套自動切換和檢索frame的機制。具體代碼如下:
需要注意的是:如果頁面中多個frame中,存在相同的xpath元素。還是需要指定frame的路徑,否則會返回搜索到的第一個元素。
強制等待
直接調(diào)用系統(tǒng)time.sleep函數(shù),不管頁面加載情況一定會等待指定的時間, 即使元素已被加載 。
1.如果設(shè)置的時間較長,會浪費時間
2.如果設(shè)置的時間較短,元素可能沒有加載。
頁面中某元素如果未能立即加載,隱式等待告訴WebDriver需等待一定的時間,然后去查找元素。默認不等待,隱式等待作用于整個WebDriver周期,只需設(shè)置一次即可。
1.在上文的find_element函數(shù)中,采用遞歸方式在所有frame尋找元素。若采用隱式等待,則在每個frame中都需要等待設(shè)定的時間,耗時非常長。
2.某些頁面我們想要的元素已經(jīng)加載完畢,但是部分其他資源未加載。隱式等待必須等待所有元素加載完畢,增加額外等待時間。
顯示等待一般作用于某一個元素,在設(shè)定的時間范圍內(nèi),默認每間隔0.5秒查找元素。返回被加載的元素,若超過設(shè)定的時間范圍未能查找則報錯。顯示等待作為selenium常用的等待機制,我們來看下他的源碼和機制。
driver 注釋中解釋為WebDriver實例,但是代碼中并未有相關(guān)檢測,因此可以傳入任何對象
但是__repr__函數(shù)中使用到session_id屬性,如果需要顯示屬性或者轉(zhuǎn)為str對象,最好在driver對象中添加session_id屬性
在until函數(shù)中,我們可以看到driver對象傳入method函數(shù)。在計時結(jié)束前,在不斷循環(huán)執(zhí)行method函數(shù),如果method函數(shù)有正常返回值則退出循環(huán),否則報TimeoutException錯誤。
可以采用裝飾器對隱式等待進行封裝,這樣代碼更加精簡
同樣的,采用裝飾器對其他常用的函數(shù)進行封裝,例如強制等待、點擊、輸入文本等。
裝飾器雖然很方便,但也會產(chǎn)生一些麻煩。例如在find_element函數(shù)遞歸調(diào)用過程中,理應(yīng)只要執(zhí)行一次裝飾器函數(shù)。但因為裝飾器已經(jīng)裝飾完畢,導(dǎo)致每次遞歸都會執(zhí)行。例如強制等待的sleep函數(shù),如果遞歸次數(shù)越多等待時間越長。
解除裝飾器一般有兩種做法:一是約定參數(shù),當(dāng)遞歸第二次調(diào)用時則不生效。例如
這種方式實現(xiàn)簡單,容易理解。但是增加了參數(shù)限制,在fun函數(shù)中就不能使用first_sleep參數(shù)。
二是采用裝飾器采用wrapped實現(xiàn),通過訪問wrapped屬性獲得原始函數(shù)。例如
但是某一個函數(shù)被多個裝飾器裝飾時,需要遞歸解除裝飾器。例如
最后整體代碼如下
這次的封裝其實還存在很多問題
1.find_element函數(shù)不僅僅只是提供查找元素功能,還提供一些其他功能,因此叫element_operation更為合適。
2.find_element函數(shù)的參數(shù)過多,并且很多參數(shù)的使用并不在函數(shù)本身中,對代碼閱讀很不友好。
3.得小心避免參數(shù)重復(fù)問題,假設(shè)裝飾器sleep和裝飾器wait_time都使用time這個參數(shù),將無法區(qū)分具體是哪個函數(shù)使用。
4.不利于擴展和維護,當(dāng)功能過多時find_element的參數(shù)過于龐大。
如果只是簡單地封裝和使用,上面這種方式也能達到較好的效果。如果想進一步封裝,建議采用鏈式調(diào)用方式,裝飾器輔助封裝。例如
這樣函數(shù)的擴展性和可閱讀性有較大的提升
看了你發(fā)的函數(shù):
def Wait(self):
self._app.MainLoop()
看名字應(yīng)該是啟動了阻塞循環(huán),去處理app的請求,這個就是需要一直運行的,因為一旦停止了,你的app請求就沒發(fā)處理了。
如果你需要啟動后再執(zhí)行的別的程序,可以使用多進程,把這個啟動放在別的進程里去執(zhí)行。
如果解決了您的問題請采納!
如果未解決請繼續(xù)追問
d = s.recv(1024)
這段代碼的返回值通過使用 not d 判斷總是失敗,于是那個循環(huán)讀取的 while 就陷入了死循環(huán),請各位幫忙看一下,謝謝!
#-*- coding:utf8 -*-
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("", 80))
s.send("GET / HTTP/1.1\r\nHost:\r\n\r\n")
tmp = []
while True:
d = s.recv(1024)
if not d:
break
tmp.append(d)
data = ''.join(tmp)
s.close()
header, html = data.split("\r\n\r\n", 1)
print header
with open("oschina.html", "wb") as f:
f.write(html)
很簡單,新建一個線程即可
import threading
def input_func( context ):
context[ 'data' ] = input( 'input:' )
context = { 'data' : 'default' }
t = threading.Thread( target = input_func ,args = ( context , ) )
t.start( )
t.join( 10 )#等待10秒
print( context )