2017-04-22 15 views
12

私はユーザ名のリストを持っており、ユーザがnet user \domain | find somegroupを使って特定のWindowsユーザグループにいるかどうかを試してみるようにしています。将来の呼び出しを行い、Pythonで完了するまで待つ方法は?

問題は、ユーザー名あたり約8人のユーザーグループに対してこのコマンドを実行すると、遅くなることです。私は先物を使ってこれらの呼び出しを送りたいと思っています。

私は何かをする前に最後を待たなければなりません。どのように私は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 

答えて

8

を生成する必要があります(この答えは現在、あなたのコードを解析するHTMLを無視...あなたは同じように、このアプローチはnet userのコールをキューにどのようにプールにそれをキューに入れることができない)

まず、を(user, group)とし、必要な情報を返す関数を定義します。

# 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) 

今、私たちは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() 

results(user, group, data)タプルのリストを使用しているスレッドプールでこれを実行することができますし、あなたが望むように処理することができます。

注:このコードが原因のpython 3ではプラットフォーム

1

producer consumer problemのようです。

メインスレッドがタスクに

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

差に現在テストされていない、より簡便な溶液がconcurrent.futuresを使用することです。

concurrent.futuresモジュールは、非同期にコール可能なコールを実行するための高レベルのインターフェイスを提供します。 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))) 

ここmax_workersスレッドの最大数を意味することに注意してください。

hereを参照してください。

EDIT:

あなたは別々のスレッドで各チェックを行う必要がある場合:

@donkopotamusに触発
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)) 

itertools.productは、すべてのターゲットを生成するために、ここで使用することができます。

そして、あなたは例外を処理する必要がない場合、それははるかに簡単で、次のようになります。

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) 
関連する問題