標籤:tip als name add 工作 daemon nim roc ip地址分配
在測試環境搭建的過程中,經常需要給伺服器分配靜態IP地址,由於不清楚當前區域網路內部哪些IP地址是閒置,所以經常需要一個一個的去試,才能找到一個可用的IP。在之前的一家公司工作的時候,用到過一個檢測IP使用方式的工具,但是屬於內部工具,無法擷取到。於是乎便想,何不自己開發一個呢?
說做便做,開發環境使用的是Python3.6+PyQt5. 如果你的環境不一樣,可能會運行失敗。
源碼地址:https://github.com/donglin-zhang/easyPing--python3.6
1、介面設計
介面用QtDesigner來畫的,先來一張原型圖如下,每次只能測試一個網段的IP佔用情況,0-255個小窗格用來顯示IP地址的使用方式,預設為灰色,程式執行後,IP地址已使用的顯示綠色,IP地址未被使用的顯示紅色。
做介面的時候,255個小窗格畫起來實在是要人命,於是就僅畫出了視窗架構,將UI檔案轉成Python源碼後,自己手動編寫代碼來實現255窗格布局。程式碼片段如下:
self.gridlayout = QtWidgets.QGridLayout(self.widget1) self.gridlayout.setContentsMargins(0, 0, 0, 0) self.gridlayout.setObjectName("gridlayout") self.gridlayout.setSpacing(7) self.label_list = [] list_index = 0 for i in range(1, 17): for j in range(1, 17): label = QtWidgets.QLabel(self.widget1) label.setMinimumSize(QtCore.QSize(32, 15)) label.setStyleSheet("background-color: rgb(203, 203, 203);") label.setAlignment(QtCore.Qt.AlignCenter) label.setText(QtCore.QCoreApplication.translate("MyPing", str(list_index))) self.label_list.append(label) self.gridlayout.addWidget(label, i-1, j-1, 1, 1) list_index += 1
2、ping功能實現
ping的實現方法有多種,最常用的當然是通過調用系統內建的ping功能來實現。
Python來執行系統命令的方式有os.system(), os.popen(), subprocess等方法,在Python3.6的手冊中表明,subprocess模組是用來替代os.system等函數的。因此我們也使用subprocess模組來調用ping
python3.5中,subprocess增加了一個run函數,run函數建立有一個子進程來運行需要執行的命令,返回一個CompletedProcess執行個體,該函數基本上可以處理所有的應用情境,run是對subprocess.Popen的一層封裝。
python3.5以下可以使用subprocess.call(), subprocess.check_call()等函數來實現相同的功能,具體可查閱Python手冊
def get_ping_result(self, ip): ‘‘‘ 檢查對應的IP是否被佔用 ‘‘‘ cmd_str = "ping {0} -n 1 -w 600".format(ip) DETACHED_PROCESS = 0x00000008 # 不建立cmd視窗 try: subprocess.run(cmd_str, creationflags=DETACHED_PROCESS, check=True) # 僅用於windows系統 except subprocess.CalledProcessError as err: self._ping_signal.emit(False, ip) else: self._ping_signal.emit(True, ip)
說明:
在預設情況下,使用subprocess.run()執行ping命令的時候,會彈出一個cmd視窗,當256個線程一起啟動並執行時候,滿屏的視窗,想想都很酸爽。。。
在windows系統下,可以傳入creationflags參數來使subprocess建立的子進程不產生console
參考連結:https://stackoverflow.com/questions/7006238/how-do-i-hide-the-console-when-i-use-os-system-or-subprocess-call
check參數為True時,函數將檢測執行結果是否為0(此處0表示執行成功),非零則拋出異常。
3、多線程
在使用pyqt進行GUI編程的時候,如果涉及到需要長時間後台啟動並執行操作,一般需要使用多線程的方式,否則介面會阻塞,直到後台運行結束,造成程式卡死的假象。
在本程式實現,要實現256個地址的ping操作,如果單線程操作,肯定半天也無法得到結果,因此我們為每一個IP地址分配一個線程,最多256線程並發運行,1~2秒的時間即可得到整個網段的IP地址佔用情況
多線程實現核心代碼如下:
def start_ping(self): ‘‘‘ 啟動多線程 ‘‘‘ self.reset_ui() startip = self.ui.startIP.text().split(‘.‘) endip = self.ui.endIP.text().split(‘.‘) tmp_ip = startip pthread_list = [] for i in range(int(startip[3]), int(endip[3]) + 1): tmp_ip[3] = str(i) ip = ‘.‘.join(tmp_ip) pthread_list.append(threading.Thread(target=self.get_ping_result, args=(ip,))) for item in pthread_list: item.setDaemon(True) item.start()
子線程通過發射訊號的方式來通知主程式執行結果,最終主程式根據運行結果渲染介面。
全部源碼可到GitHub下載,連結見文章頭部。
使用Python檢測區域網路內IP地址使用方式