在Python中,for循环一个文件来搜索另一个文件
如果能提供一些关于如何增强python脚本以解决问题的线索,我将不胜感激。我有一个文件,其中列出了数千个移动工作站和IP地址,每五分钟更新一次。我使用Paramiko将ssh连接到每个工作站,以验证服务是否正在运行(在本例中为crond)。我遇到的问题是,当我启动python脚本时,它会将大文件读入内存,当它读入内存的1/3时,IP地址已经更改,大部分IP地址不再有效。是否有一种方法可以在每次搜索之前让python打开然后关闭文件?这将确保IP为当前IP。我在下面编写的python脚本可以正常工作,但我还是遇到了旧IP信息的问题。多谢各位在Python中,for循环一个文件来搜索另一个文件,python,paramiko,readlines,Python,Paramiko,Readlines,如果能提供一些关于如何增强python脚本以解决问题的线索,我将不胜感激。我有一个文件,其中列出了数千个移动工作站和IP地址,每五分钟更新一次。我使用Paramiko将ssh连接到每个工作站,以验证服务是否正在运行(在本例中为crond)。我遇到的问题是,当我启动python脚本时,它会将大文件读入内存,当它读入内存的1/3时,IP地址已经更改,大部分IP地址不再有效。是否有一种方法可以在每次搜索之前让python打开然后关闭文件?这将确保IP为当前IP。我在下面编写的python脚本可以正常工
The contents of WKSIPS.txt are in the format:
WORK 1234 Cell IP: 10.10.10.10
WORK 4567 Cell IP: 10.10.10.11
#!/usr/bin/python
import paramiko, os, string, threading
import getpass
import socket
import sys
FileName=open('WKSIPS.txt', 'r')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for line in FileName.readlines():
WKSid = line.split()
try:
if WKSid[0] == 'WORK' :
WKSip = WKSid[4]
ssh.connect(WKSip, username='user', password='password', timeout='3')
stdin, stdout, stderr = ssh.exec_command('service crond status')
Out = stdout.readlines()
print ("WORK " + WKSid[1], Out)
ssh.close()
FileName.close
except paramiko.SSHException, e:
print ('WORK' + WKSid, WKSip, "Invalid Password")
这是非常昂贵的,但我认为这是检验这种方法是否适用于您的第一步:
import re
import paramiko
def verify_service(ssh, work, ip):
print("Verifying workstation %d at %s" % (work, ip))
ssh.connect(ip, username='user', password='password', timeout='3')
stdin, stdout, stderr = ssh.exec_command('service crond status')
print ("WORK " + work, stdout.readlines())
ssh.close()
IP_LIST = 'WKSIPS.txt'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Get number of lines in WKSIPS -- if you know this, you can just define NUM_LINES
NUM_LINES = None
with open(IP_LIST) as f:
NUM_LINES = len(f.readlines())
for i in xrange(NUM_LINES):
with open(IP_LIST) as f:
#line = f.readlines()[i]
line = next(islice(f, i, None))
mat = re.match(r'WORK\s*(\d+)\s*Cell IP: (.*)', line)
if mat:
verify_service(ssh, int(mat.group(1)), mat.group(2))
代码首先打开文件并计算行数,将其存储在NUM\u行中。如果您知道这个数字,您可以去掉NUM\u line=None
行和它下面的两行,只需将其替换为NUM\u line=
然后,对于0到NUM_LINES
(独占)之间的每个行号i
,它打开文件,将整个文件读入一个列表,拉出与行号i
对应的行,在这些行上迭代,直到到达i
第行,解析它并将其传递给verify_服务()
函数——您必须使用paramiko代码更新该函数
如果这样做有效,你应该考虑更好的方法。也许你不必每次迭代都重新读取文件,也许每n次迭代都可以。也许您可以对文件进行哈希,并在重新读取之前检查哈希是否已更改。可能检查文件的修改时间等。可能使用子进程并尝试同时处理多个连接,而不是连续处理
在任何情况下,如果这样做有效,您应该寻求对其进行优化——因为它目前的编写成本非常高,但它可以满足您的要求。我建议使用创建一个工人,可以为您处理文件的每一行,这将允许您更快地完成文件
我使用此代码段的目标是通过使脚本足够快,在5分钟的文件刷新之前完成,从而完全避免文件重新加载问题
#!/usr/bin/python
import paramiko, os, string, threading
import multiprocessing
import getpass
import socket
import sys
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
def worker(line)
WKSid = line.split()
try:
if WKSid[0] == 'WORK' :
WKSip = WKSid[4]
ssh.connect(WKSip, username='user', password='password', timeout='3')
stdin, stdout, stderr = ssh.exec_command('service crond status')
Out = stdout.readlines()
print ("WORK " + WKSid[1], Out)
ssh.close()
except paramiko.SSHException, e:
print ('WORK' + WKSid, WKSip, "Invalid Password")
# set up processing pool
pool = multiprocessing.Pool()
with open('WKSIPS.txt') as infile:
pool.map(worker, infile)
pool.close()
pool.join()
注:
- 我已经将脚本功能的主要部分移动到一个函数中,该函数接受一行文件作为输入
pool.map()
将为每个工作人员提供一行文件迭代器,他们将独立处理它。它所做的工作与您的原始代码相同,但工作被分配到多个进程中,这些进程的数量等于您机器上的内核数量
- 我没有paramiko模块,也无法在我当前的环境中安装它,因此我无法真正为您测试此代码。如果有任何错误,我将提前道歉
- 我不熟悉paramiko库,因此在多个进程中同时使用相同的
paramikio.SSHClient()
对象可能会产生一些隐藏的副作用。如果从ssh
对象中看到异常错误,请尝试将其实例化移动到worker函数中
- 我已将
readlines()
更改为使用Python文件迭代器。将整个文件读入内存是一项耗时的操作,应该避免
非常清楚的是,此代码段不会处理文件运行时发生的更改。我做了两大假设:
此脚本的执行可以与刷新文件的任何操作同步,以便在刷新文件后立即执行
它可以在5分钟内执行-因为我没有paramiko、ssh目标访问权限或WKSIPS.txt访问权限,所以我无法计时。由于这个问题似乎符合的定义,我认为值得一试。如果不符合时间规格,则由OP进一步优化
如果按照您的建议关闭并重新打开该文件,是否希望从“新”文件的开头重新开始?还是跟你说的一样?从同一行开始是否会导致任何问题(例如,行数发生变化)?您可以使用来并行执行某些工作。至少,您可以让子进程执行ssh工作,这样您就不会阻止文件读取。因为此工作站名称是静态的,并且只有IP地址更改,所以我需要它从中断的地方开始。行的顺序是否更改?行数是否更改?如果在无效IP地址上运行命令,会发生什么情况?这是一个您可以识别并选择忽略的事件吗?多处理池方法似乎是个好主意,但在当前编写代码时不会反映对文件运行中期的更改。这是事实。我假设此脚本的运行可以与文件刷新同步。我将编辑以澄清这一点。我感谢多处理建议,但由于这些工作站中的一些通过无线电连接,因此很难在五分钟内完成。目前,按照我写的方式,由于建立ssh连接的延迟,它需要4个多小时。@gineraso哦。该死的。这是一个好主意。@gineraso不管它值多少钱,我仍然建议您在理顺文件刷新处理之后实现某种并行性。对于处理SSH连接的多个进程,您仍然可以看到运行时间的显著减少。让我给你一个解决方案,看看它是否符合我的需要。非常感谢。