2017-09-05 86 views
0

美好的一天,即時通訊嘗試掌握python中的異步東西,並陷入了一種應該很容易解決的情況,但我仍然感到沮喪,我做錯了什麼。建議我有一個代理列表,我想檢查服務器是否已啓動並正在運行,更重要的是我想以異步方式執行它,不幸的是,與同步功能的比較顯示執行時間相同。Python異步代理狀態檢查

所以,代碼:

import requests 
import os 
import asyncio 

from lxml import html 


class GetUkProxy: 
    url = "https://free-proxy-list.net/uk-proxy.html" 

    def __init__(self): 
     self.getProxyList(self.url) 

    def getProxyList(self, url): 
     self.proxies = [] 
     data = requests.get(url) 
     response = html.fromstring(data.text) 
     for item in response.xpath('//table[@id="proxylisttable"]/tbody/tr'): 
      ip, port = item.getchildren()[:2] 
      self.proxies.append({'IP': ip.text, 'Port': port.text, 'Status': 'unknown'}) 

    def printProxies(self): 
     try: 
      for proxy in self.proxies: 
       print(proxy['IP'] + ':' + proxy['Port'], proxy['Status']) 
     except: 
      print("Proxy list is empty") 

    def checkProxies(self): 
     loop = asyncio.get_event_loop() 
     data = loop.run_until_complete(self.checkProxyList()) 
     loop.close() 


    async def checkProxyList(self): 
     try: 
      tasks = [] 
      for proxy in self.proxies[:10]: 
       task = asyncio.ensure_future(self.checkProxy(proxy)) 
       tasks.append(task) 
      await asyncio.gather(*tasks) 
     except: 
      print('Proxy list is empty') 

    async def checkProxy(self, proxy=None): 
     try: 
      check = os.system('ping -n 4 -w 2 ' + proxy['IP']) 
      if not check: 
       proxy['Status'] = 'Dead' 
      else: 
       proxy['Status'] = 'Alive' 
     except Exception as exp: 
      print(exp) 

    def syncCheck(self): 
     for item in self.proxies[:10]: 
      check = os.system('ping -n 4 -w 2 ' + item['IP']) 

異步checkProxies的執行時間等於同步syncCheck的執行時間,所以任何想法是錯誤的根源,以及如何解決它是歡迎。

回答

1

os.system是一個阻止事件循環的同步函數。

您可以使用asyncio.create_subprocess_exec異步執行系統命令,並阻止事件循環。

async def checkProxy(self, proxy=None): 
    try: 
     check = await asyncio.create_subprocess_exec(
      'ping', '-c', '4', '-W', '2', proxy['IP'], stdout=asyncio.subprocess.PIPE) 
     out, error = await check.communicate() 

     proxy['Status'] = 'Alive' 

     if error: 
      proxy['Status'] = 'Dead' 
    except Exception as exp: 
     print(exp) 

編輯:checkProxies方法我們將做期貨的列表一起運行。

def checkProxies(self): 
    loop = asyncio.get_event_loop() 
    proxies = self.proxies[:10] 
    tasks = [self.checkProxy(proxy) for proxy in proxies] 


    loop.run_until_complete(
     asyncio.gather(
      *tasks 
     ) 
    ) 

    loop.close() 

uk = GetUkProxy() 
uk.checkProxies() 
print(uk.proxies) 
+0

感謝隊友,那救了我一天! Offtop:你能否建議一些書/文章/教程來研究asyncio的東西,就像你在答案中展示的那樣? –

+0

嗯,有一個問題 - 雖然它執行得很快,但似乎是出錯和未填充 - 執行後的代理狀態仍然是「未知」。你能否再次看看你的代碼。 –

+0

這是因爲我們在切分'self.proxies [:10]'時使用'self.proxies'的副本。作爲參考,你可以看到['vanheem' slide here](https://github.com/vangheem/asyncio-presentation/tree/master)和[ProgrammerCreek中的示例](https://www.programcreek.com/python/index/5526/asyncio) –