zoukankan      html  css  js  c++  java
  • Python拷贝及多进程与类的问题

    最近写python写的尤其不顺利,更多的debug,逐渐的深入,产出却比较少。应该是个瓶颈期,坚持坚持,厚着脸皮也要坚持下去。

    0x00 拷贝问题

    程序中涉及到多进程和协程,大致的模型是开了2+个进程,每个进程里再开协程(提高多核CPU利用率)。又因为Python的multiprocessing和gevent是对头,某些东西不兼容(比如gevent和multiprocessing.Manager不能同时出现),所以虽然每个进程中做的操作(弱口令扫描)类似,结果存储以及进度方面都是在各个进程里完成的。于是就有了这样的代码:

    def process_run():
        pool = Pool(3)
    
        for count in range(4):
            pool.apply_async(gevent_run, args(,))
    
        pool.close()
        pool.join()
    
    
    def gevent_run():
        num_count = 0
        pool = Pool(150)
    
        for count in range(500):
            pool.add(gevent.spawn(verify_and_count, num_count))
    
        pool.join()
    
    def verify_and_count(count):
        if poc.verify():
            count += 1
    
        if count % 100 == 0:
            print"Progress: %d/%d" % (count, all_count)

    可以看到我在gevent_run函数里声明了一个num_count变量用于计数(当前扫描进度),也就是为每个进程都申请了一个这样的变量。但是在实际运行的时候,发现并没有输出进度信息,排查后发现count始终为0。

    之前在一篇文章里看过Python的拷贝问题,在List和dict的时候,直接传参或者赋值是不会改变对应的变量在内存中的位置的,比如:

    >>> a = [1,2,4]
    >>> id(a)
    42176920
    >>> b = a
    >>> id(b)
    42176920

    但是理解有些错误,以为所有的赋值都不会改变。实际上,如果=的右侧是一个新的变量的话,也会创建全新的内存空间,无论是int还是list:

    >>> a = [1,2,4]
    >>> id(a)
    42176920
    >>> b = a
    >>> id(b)
    42176920
    >>> a = a + [2,3]
    >>> a
    [1, 2, 4, 2, 3]
    >>> id(a)
    42214744

    最后解决这个问题,还是用到了list局部赋值,不会改变list本身位置的特点:

    >>> a = [0]
    >>> id(a)
    42214744
    >>> id(a[0])
    14514580
    >>> a[0] += 1
    >>> id(a)
    42214744
    >>> id(a[0])
    14514568

    0x10 多进程和类对象的问题

    class test():
        def bb(self, a):
            print a
    
        def run(self):
            pool = Pool(processes=2)
    
            for count in range(4):
                pool.apply_async(self.bb, args=(count,))
    
            pool.close()
            pool.join()

    程序看起来没什么问题,但是在实际执行的时候,并没有调用bb函数。但如果是调用非成员函数,就没什么问题。后来同事给出了解决方法:

    class test():
        def bb(self, a):
            print a
    
        def run(self):
            pool = Pool(processes=2)
    
            for count in range(4):
                pool.apply_async(self.bb())
    
            pool.close()
            pool.join()

    看起来是解决了问题,但实际上并没有用到multiprocessing,直接变成了循环函数。后来查了一下资料,得出的结论:

    Python2.7 多进程multiprocessing使用的pipe传递方法,实现用的是C pickle_dumpsm,这种方式不支持 instance method 传递。
    所以,最一开始的传递方式无效,实际是因传递失败:子进程不会进行检查即不会报错,母进程作为僵尸等待,而子进程无效停止造成母进程结束退出。

    http://stackoverflow.com/questions/14169550/how-to-use-multiprocessing-with-class-instances-in-python

    http://stackoverflow.com/questions/27318290/why-can-i-pass-an-instance-method-to-multiprocessing-process-but-not-a-multipro

    最后的解决方法,是把多进程和协程的调度函数放在了类外,这也应该是多进程和类掺和到一块儿的时候,正确的解决办法了吧。

    0x20 VMware虚拟机 网络失效 解决方案

    今天NAT的网络上不去了,纠结了两个小时,试了很多方案,最后也不知道是哪个起作用了。干脆总结个方法:

    1) 我的电脑 - 右键 - 管理 - windows服务 : 开启所有vmware相关的服务,已经开启的重新启动。另外还要开启windows installer。

    2) 虚拟机 - 网络首选项 - 恢复默认设置

    3) 对应的虚拟机 - 删除原有网卡 - 添加新网卡

    4) 删除/etc/network/interfaces里的内容,重新启动网卡

  • 相关阅读:
    HDU 1162 Eddy's picture (最小生成树)(java版)
    codeforces 735D Taxes(数论)
    codeforces 735C Tennis Championship(贪心+递推)
    codeforces 2B The least round way(DP+数学)
    codeforces 2A Winner (好好学习英语)
    codeforces 632C The Smallest String Concatenation
    codeforces 803D Magazine Ad(二分+贪心)
    codeforces 803C Maximal GCD(GCD数学)
    codeforces 803B Distances to Zero
    STL容器之优先队列(转)
  • 原文地址:https://www.cnblogs.com/kuoaidebb/p/4918896.html
Copyright © 2011-2022 走看看