2017-04-22 19 views
12

Tôi có mã sau đây, trong đó tôi có danh sách tên người dùng và tôi thử kiểm tra xem người dùng có thuộc Nhóm sử dụng Windows cụ thể không bằng cách sử dụng net user \domain | find somegroup.Làm thế nào để thực hiện cuộc gọi trong tương lai và đợi cho đến khi hoàn thành với Python?

Vấn đề là tôi chạy lệnh đó cho khoảng 8 nhóm người dùng trên mỗi tên người dùng và nó chậm. Tôi muốn gửi các cuộc gọi này bằng cách sử dụng tương lai và thậm chí tách riêng các chủ đề (nếu nó làm cho nó nhanh hơn).

Tôi chỉ phải đợi ở cuối trước khi tôi làm bất cứ điều gì khác. Làm thế nào để tôi thực hiện nó bằng Python?

for one_username in user_list: 
    response = requests.get(somecontent) 

    bs_parsed = BeautifulSoup(response.content, 'html.parser') 

    find_all2 = bs_parsed.find("div", {"class": "QuickLinks"}) 
    name = re.sub("\s\s+", ' ', find_all2.find("td", text="Name").find_next_sibling("td").text) 

    find_all = bs_parsed.find_all("div", {"class": "visible"}) 
    all_perms = "" 
    d.setdefault(one_username + " (" + name + ")", []) 
    for value in find_all: 
     test = value.find("a", {"onmouseover": True}) 
     if test is not None: 
      if "MyAppID" in test.text: 
       d[one_username + " (" + name + ")"].append(test.text) 

    for group in groups: 
     try: 
      d[one_username + " (" + name + ")"].append(check_output("net user /domain " + one_username + "| find \"" + group + "\"", shell=True, stderr=subprocess.STDOUT).strip().decode("utf-8")) 
     except Exception: 
      pass 

Trả lời

8

(Câu trả lời này đang bỏ qua HTML phân tích mã của bạn không ... bạn có thể xếp hàng đó vào một hồ bơi y hệt cách tiếp cận này hàng đợi các net user cuộc gọi)

Trước tiên, hãy xác định hàm cần có tuple của (user, group) và trả về thông tin mong muốn.

# a function that calls net user to find info on a (user, group) 
def get_group_info(usr_grp): 
    # unpack the arguments 
    usr, grp = usr_grp 

    try: 
     return (usr, grp, 
       check_output(
        "net user /domain " + usr + "| find \"" + grp + "\"", 
        shell=True, 
        stderr=subprocess.STDOUT 
        ).strip().decode("utf-8"))) 
    except Exception: 
     return (usr, grp, None) 

Bây giờ, chúng ta có thể chạy trong một hồ bơi thread sử dụng multiprocessing.dummy.Pool

from multiprocessing.dummy import Pool 
import itertools 

# create a pool with four worker threads 
pool = Pool(4) 

# run get_group_info for every user, group 
async_result = pool.map_async(get_group_info, itertools.product(user_list, groups)) 

# now do some other work we care about 
... 

# and then wait on our results 
results = async_result.get() 

Các results được một danh sách các (user, group, data) tuples và có thể được xử lý như bạn mong muốn.

Lưu ý:Mã này hiện chưa được kiểm tra do một sự khác biệt trong các nền tảng

1

Có vẻ như producer consumer problem.

Các chủ đề chính sẽ tạo ra những nhiệm vụ

class Task: 
    def Task(self,user,group) 
     self.user = user 
     self.group = group 
    def run(self): 
     pass # call command with self.user and self.group and process results 

twp = TaskWorkerPool(4) 
for group in groups: 
    twp.add(Task(user,group)) 
twp.wait() 
1

Trong python 3, một giải pháp đơn giản và thuận tiện hơn là sử dụng concurrent.futures.

Mô-đun concurrent.futures cung cấp giao diện cấp cao để thực hiện cuộc gọi không đồng bộ. Reference...

import concurrent.futures 


# Get a list containing all groups of a user 
def get_groups(username): 
    # Do the request and check here 
    # And return the groups of current user with a list 
    return list() 

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: 
    # Mark each future with its groups 
    future_to_groups = {executor.submit(get_groups, user): user 
         for user in user_list} 

    # Now it comes to the result of each user 
    for future in concurrent.futures.as_completed(future_to_groups): 
     user = future_to_groups[future] 
     try: 
      # Receive the returned result of current user 
      groups = future.result() 
     except Exception as exc: 
      print('%r generated an exception: %s' % (user, exc)) 
     else: 
      # Here you do anything you need on `groups` 
      # Output or collect them 
      print('%r is in %d groups' % (user, len(groups))) 

ý rằng max_workers đây có nghĩa là số tối đa của chủ đề.

Xem here nơi ví dụ này đến từ đó.

EDIT:

Nếu bạn cần làm mỗi lần kiểm tra trong chủ đề riêng biệt:

import concurrent.futures 


# Check if a `user` is in a `group` 
def check(user, group): 
    # Do the check here 
    # And return True if user is in this group, False if not 
    return True 

with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: 
    # Mark each future with its user and group 
    future_to_checks = {executor.submit(check, user, group): (user, group) 
         for user in user_list for group in group_list} 

    # Now it comes to the result of each check 
    # The try-except-else clause is omitted here 
    for future in concurrent.futures.as_completed(future_to_checks): 
     user, group = future_to_checks[future] 
     in_group = future.result() 
     if in_group is True: 
      print('%r is in %r' % (user, group)) 

Lấy cảm hứng từ @donkopotamus, itertools.product có thể được sử dụng ở đây để tạo ra tất cả các mục tiêu.

Và nếu bạn không cần phải xử lý các trường hợp ngoại lệ, nó sẽ đơn giản hơn nhiều:

import concurrent.futures 
from itertools import product 
from collections import defaultdict 


def check(target): 
    user, group = target 
    return True 

with concurrent.futures.ThreadPoolExecutor() as executor: 
    results = defaultdict(list) 
    targets = list(product(user_list, group_list)) 
    for (user, group), in_group in zip(targets, executor.map(check, targets)): 
     if in_group is True: 
      results[user].append(group) 

    print(results) 
Các vấn đề liên quan