【问题标题】:Python: Strange output for threaded ARP pingPython:线程 ARP ping 的奇怪输出
【发布时间】:2014-03-19 18:16:15
【问题描述】:

感谢您花时间看这个!

我遇到的问题是我的线程化 ARP 脚本的输出。我想要实现的是将每个活动主机的 IP 地址、MAC 地址和 NIC 供应商输出到命令提示符。

我有一个没有线程的旧 ARP 脚本,大约需要 90 秒并打印出我理想的输出。

下面是我的新脚本,基于上述脚本,带有线程。不幸的是,我不知道为什么输出中没有显示任何值。如果有人可以提供帮助,我将非常感激!

提前致谢!

def arp2(ip):

    # An ARP scanner for the network.
    ips = []

    global ans, unans
    ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip), timeout=2, verbose=0)

    for snd, rcv in ans:
    #Assign MAC address and IP address to variables mac and ipaddr

        mac = rcv.sprintf(r"%Ether.src%")
        ipaddr = rcv.sprintf(r"%ARP.psrc%")

        #Get NIC vendor code from MAC address
        niccode = mac[:8]
        niccode = niccode.upper()

        print ips
        ips.append("end")

        #ARPips file amendments
        with open( 'C:\Python26\ARPips.prn', 'w+') as f:
            f.write("\n".join(map(lambda x: str(x), ips)) + "\n")

        #String lookup for NIC vendors. DO NOT CHANGE 'r' TO ANY OTHER VALUE.
        with open('C:\Users\TomVB\Desktop\OID2.prn', 'r') as file:
            for line in file:
                if niccode in file:
                    return mac, ipaddr, line[8:]




def main():

    print "Discovering..."
    print ""
    print "MAC Address \t \t  IP Address \t  NIC Vendor"


    pool = Pool(processes=12)

    Subnetlist = []

    for i in range(255):
        Subnetlist.append(str(IPInt+str(i)))

    global ARPresults
    ARPresults = pool.map(arp2, Subnetlist)

    pool.close()
    pool.join()


    print "\n".join(ARPresults)

if __name__ == '__main__':
    main()

这个脚本给了我以下输出:

Mac Address    IP address      NIC Vendor

[][]

[]

[]

[]
 []
[][]
[]

[]  

以此类推,大约 200 行。

【问题讨论】:

  • 嘿@J.F.Sebastian,谢谢你看这个,我写这个脚本的时候就是这么想的。您知道为什么即使返回了 mac 和 ipaddr 并且 map 拾取了它们,它为什么不打印吗?我觉得我错过了一些非常明显的东西):
  • 上一个问题的第一个问题:ping() 不返回任何内容,但您正在尝试打印其结果。 arp2() 是否返回任何内容?
  • 无关:帮助您学习:1.从您的代码中删除global(您不需要它) 2.a 不要在多个进程中覆盖同一文件ARPips.prn。充其量只有一个进程可以编写结果。 2.b 不要在子进程中打印,将所有结果返回给父进程并写入文件并在那里打印。
  • 感谢@J.F.Sebastian 的提示,与获得正确答案同样有价值:)

标签: python multithreading output arp


【解决方案1】:

首先,您似乎正在使用多处理而不是线程。这两个行为完全不同,我建议你调查一下。无论如何,对于手头的问题,原因在别处。

arp2 方法是并行执行的。我发现该方法存在两个问题:

print "%s \t  %s  \t  %s" % (mac, ipaddr, line[8:])

此语句打印到标准输出。在我们的代码中,它可能由多达 12 个进程同时执行。 Python 不保证print 语句是原子的。当下一个进程写他的行时,很可能会发生一个进程已经写了一半的行。简而言之,您的输出会变得一团糟。

同样适用

with open( 'C:\Python26\ARPips.prn', 'w+') as f:
    f.write("\n".join(map(lambda x: str(x), ips)) + "\n")

同样不能保证这些进程不会相互影响。文件内容可能会被篡改。

最简单的解决方案是不要在arp2 方法内执行任何文件或控制台输出。而是返回结果。 pool.map 将以安全的方式为您收集这些结果。它的行为类似于常规的 map 函数。然后你可以将它们输出到文件和控制台。

如果您想在扫描运行时输出,您必须同步进程(例如使用multiprocessing.Lock。这样只有一个进程会同时写入/打印。

还有:

  • 在具有 Windows 样式路径的字符串文字前面放置一个“r”:x = r'C:\Users\TomVB\Desktop\OID2.prn'。反斜杠用于在 Python 中转义。

  • C:\Users\TomVB\Desktop\OID2.prn 的内容加载到dict 中。它会快得多。

  • map(lambda x: str(x), ips) 等于map(str, ips)

【讨论】:

  • 嗨@Stefan 非常感谢您的回复!我非常感谢您花时间和我一起研究这个问题。关于你的回答,我改变了这个说法: print "%s \t %s \t %s" % (mac, ipaddr, line[8:]) 到这个: return mac, ipaddr, line[8:] yet其中输出通常是,例如:[5] [3] [1] [2] [4] [1] [5] [2] [4] [5] 输出仍然与此类似:[] [] [] [] [][][] 等等。知道为什么会发生这种情况吗?
  • 请显示您正在使用的实际代码。您描述的内容与您的代码不符。如果您唯一的更改是返回一个元组,那么ARPresults 将是一个元组列表。 print "\n".join(ARPresults) 会抛出错误。还请清理未使用的代码,例如hostID += 1
  • 嗨@Stefan,我做了一些更改,声明: print "\n".join(ARPresults) 不会抛出错误,但也许这是没有值的原因显示?再次感谢您的建议:)
  • 我仍然看不到该代码如何产生该输出。 srpARPEther 是否产生任何输出?请删除global ans, unans,您可能会在这里侥幸逃脱,但是当并行运行时,您不会一个进程更改另一个进程的变量内容。您是否意识到如果在文件中找到该条目,return 之后的所有内容都不会被执行? ips 没用我看。我再说一遍:不要在没有保护的情况下在并行代码中使用printwrite。请将代码减少到证明您的问题所需的最低限度。
  • 嗨@stefan,非常感谢您对我的支持哈哈。今天早上有一个hazzah时刻。这个错误确实很愚蠢,但如果你想知道,错误是双重的。 print ips 语句多次打印一个空列表,而“if niccode in file”应该是“if niccode in line”。通过改变这两个输出是应该的。再次感谢您和我一起看这个! :P
猜你喜欢
  • 2014-04-15
  • 2015-03-24
  • 1970-01-01
  • 2020-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-30
相关资源
最近更新 更多