2011-12-17 131 views
0

我想更正一个脚本。但我的头是嵌套的。所以我想问问。更正Python中的打印项目

脚本是:

from xml.dom.minidom import parse 
from itertools import groupby 

yXML = parse('/root/Desktop/gb/data/yConfig.xml') 

servers = [] 
for AllConfigurations in yXML.getElementsByTagName('AllConfigurations'): 
    for DeployConfigurations in AllConfigurations.getElementsByTagName('DeployConfigurations'): 
     for Servers in DeployConfigurations.getElementsByTagName('Servers'): 
      for Group in Servers.getElementsByTagName('Group'): 
       for GApp in Group.getElementsByTagName('GApp'): 
        for Server in Group.getElementsByTagName('Server'): 
         servers.append((Server.getAttribute('name'), 
           Group.getAttribute('name'), 
           Server.getAttribute('ip'), 
           GApp.getAttribute('type'))) 

def line(machine, group, ip, services): 
    return " | ".join([machine.ljust(22), group.ljust(22), ip.ljust(18), services]) 

print line("Machine", "Group", "IP", "Services") 
print line("----------", "----------", "----------", "----------") 
for server, services in groupby(sorted(servers), lambda server: server[0:3]): 
    print line("- " + server[0], server[1], server[2], 
      ", ".join(service[3] for service in set(services))) 

XML是:

<AllConfigurations> 
     <DeployConfigurations> 
      <Servers> 
       <Group id="1" name="The Perfect Life" username="root" password="mypasswd123" state=""> 
      <GApp id="1" name="JBoss Servers" type="JBoss" path="/root/Desktop/jboss-as-7.0.2.Final/" state=""> 
       <Server id="1" name="Jboss1" ip="192.168.1.250" path="/root/Desktop/jboss-as-7.0.2.Final/" username="" password="" state="" /> 
       <Server id="2" name="Jboss2" ip="192.168.1.251" path="/root/Desktop/jboss-as-7.0.2.Final/" username="" password="" state="" /> 
       <Server id="3" name="Jboss3" ip="192.168.1.252" path="/root/Desktop/jboss-as-7.0.2.Final/" username="" password="" state="" /> 
       <Server id="4" name="Jboss4" ip="192.168.1.253" path="/root/Desktop/jboss-as-7.0.2.Final/" username="" password="" state="" /> 
      </GApp> 
      <GApp id="2" name="Tomcat Servers" type="Tomcat" path="/root/Desktop/apache-tomcat-7.0.22/" state=""> 
       <Server id="1" name="Tom1" ip="192.168.1.250" path="/root/Desktop/apachee/" username="" password="" state="" /> 
       <Server id="2" name="Tom2" ip="192.168.1.251" path="/root/Desktop/apache-tomcat-7.0.22/" username="" password="" state="" /> 
       <Server id="3" name="Tom3" ip="192.168.1.252" path="/root/Desktop/apache-tomcat-7.0.22/" username="" password="" state="" /> 
       <Server id="4" name="Tom4" ip="192.168.1.111" path="/root/Desktop/apache-tomcat-7.0.22/" username="" password="" state="" /> 
      </GApp> 
      </Group> 
     </Servers> 
    </DeployConfigurations> 
</AllConfigurations> 

电流输出是:

Machine    | Group     | IP     | Services 
----------    | ----------    | ----------   | ---------- 
- Jboss1    | The Perfect Life  | 192.168.1.250  | Tomcat, JBoss 
- Jboss2    | The Perfect Life  | 192.168.1.251  | Tomcat, JBoss 
- Jboss3    | The Perfect Life  | 192.168.1.252  | JBoss, Tomcat 
- Jboss4    | The Perfect Life  | 192.168.1.253  | JBoss, Tomcat 
- Tom1     | The Perfect Life  | 192.168.1.250  | JBoss, Tomcat 
- Tom2     | The Perfect Life  | 192.168.1.251  | Tomcat, JBoss 
- Tom3     | The Perfect Life  | 192.168.1.252  | JBoss, Tomcat 
- Tom4     | The Perfect Life  | 192.168.1.111  | JBoss, Tomcat 

的问题是:

1 - 正如你在Tom4看192.168上没有JBoss服务器。 1.111。该服务器仅适用于Tomcat。 Jboss4只有JBoss(253),其他(250,251,252)都有。服务部分不起作用。

2- IP打印多次。我不能处理它...

3-和机器列...

他们都必须是这样的:

Machine    | Group     | IP     | Services 
----------    | ----------    | ----------   | ---------- 
- Jboss1/Tom1  | The Perfect Life  | 192.168.1.250  | JBoss, Tomcat 
- Jboss2/Tom2  | The Perfect Life  | 192.168.1.251  | JBoss, Tomcat 
- Jboss3/Tom3  | The Perfect Life  | 192.168.1.252  | JBoss, Tomcat 
- Jboss4    | The Perfect Life  | 192.168.1.253  | JBoss 
- Tom4     | The Perfect Life  | 192.168.1.111  | Tomcat 

所以,我应该怎么办?

感谢

+0

你应该蒸馏这个例子。在解析XML之后打印出您的`servers` var,然后重新发布刚刚设​​置`servers = ...`的代码,并跳过与您的问题无关的整个XML解析部分。 – dkamins 2011-12-17 00:27:02

+0

我不知道你在说什么实际上。如果我跳过解析会怎么样?我可以按顺序打印其他300台服务器吗? – nightrider84 2011-12-17 00:30:18

回答

2

警告:这个答案是巨大

您的代码中存在一堆问题。

itertools.groupby()使用不当

最相关的是,你是排序和使用两个不同的关键功能分组服务器。当你对一个序列进行分组时,它应该由相同的密钥函数进行排序,以便对它进行分组。在你的情况,因为你是通过IP(这是服务器的元组的第三个要素)要组,你的功能应该是:

def get_ip(server): 
    return server[2] 

现在,你甚至还可以在服务器处理它们,为了清楚之前进行排序:

sorted_servers = sorted(servers, key=get_ip) 

groupby()迭代器将产生不同的对,包括通过密钥和产生该键的所有结果,因为你可能已经知道一个迭代器。由于关键是IP,我将按如下方式声明循环。需要注意的是功能是排序的服务器相同:

for ip, servers in groupby(sorted_servers, get_ip): 

串接值形成列

在循环中,我们会怎样做?对于每个IP,我们将获得所有机器的集合,所有组的集合*以及与IP关联的所有服务的集合。首先,我们将创建一个空集:

machine_set = set() 
    group_set = set() 
    service_set = set() 

然后,我们将遍历由groupby()对于给定的IP返回的迭代器产生的所有服务器。对于每个服务器,我们将每个服务器的信息添加到相应的设置:

for machine, group, _, service in servers: 
     machine_set.add(machine) 
     group_set.add(group) 
     service_set.add(service) 

所做的,我们将加入机,组和服务,每一套在一个字符串。然后,只需这些值传递到line()功能和打印结果:

machines = "/".join(machine_set) 
    groups = ", ".join(group_set) 
    services = ", ".join(service_set) 
    print line("- " + machines, groups, ip, services) 

检查站

为了清楚起见,所得到的代码如下。

def get_ip(server): 
    return server[2] 

sorted_servers = sorted(servers, key=get_ip) 

print line("Machine", "Group", "IP", "Services") 
print line("----------", "----------", "----------", "----------") 

for ip, servers in groupby(sorted_servers, get_ip): 
    machine_set = set() 
    group_set = set() 
    service_set = set() 
    for machine, group, _, service in servers: 
     machine_set.add(machine) 
     group_set.add(group) 
     service_set.add(service) 

    machines = "/".join(machine_set) 
    groups = ", ".join(group_set) 
    services = ", ".join(service_set) 
    print line("- " + machines, groups, ip, services) 

打印的结果是下面的一个:您可以将line()功能通过下面的代码声明之前刚刚更换所有的代码

Machine    | Group     | IP     | Services 
----------    | ----------    | ----------   | ---------- 
- Tom4     | The Perfect Life  | 192.168.1.111  | JBoss, Tomcat 
- Jboss1/Tom1  | The Perfect Life  | 192.168.1.250  | JBoss, Tomcat 
- Tom2/Jboss2  | The Perfect Life  | 192.168.1.251  | JBoss, Tomcat 
- Jboss3/Tom3  | The Perfect Life  | 192.168.1.252  | JBoss, Tomcat 
- Jboss4    | The Perfect Life  | 192.168.1.253  | JBoss, Tomcat 

由机器名称排序

这不是刚好你要求的是:行按IP排序,而不是按机器列排序。当然,这是我们之前对服务器进行排序的方式。按照您的要求进行排序,我会提出此解决方案:在for之前,在变量中创建一个列表。相反,印刷线,与值的元组追加到此列表:

lines = [] 
for ip, servers in groupby(sorted_servers, get_ip): 
    # ... Same stuff here 
    machines = "/".join(machine_set) 
    groups = ", ".join(group_set) 
    services = ", ".join(service_set) 
    # No more "print line("- " + machines, groups, ip, services)" 
    lines.append((machines, groups, ip, services)) 

然后,由元组的第一项(机器名)列表进行排序:

lines = sorted(lines, key=lambda l: l[0]) 

现在迭代在所有服务器的元组和打印线:

for machine, group, ip, service in lines: 
    print line(machine, group, ip, service) 

奖励点:去除循环庞然大物

在程序开始时,你有不少于六个嵌套for循环。男人,这是疯狂(或SPARTAAA,但都是不好的想法)。您可以轻松地删除所有这种嵌套:从yXML对象直接检索所有Server标签。从每个标签,您可以通过调用server.getAttribute('name')来获得服务器名称。 Group标签是Server标签的祖父母,因此您可以通过server.parentNode.parentNode.getAttribute('name')获取组名称。可以从服务器标签轻松检索IP:server.getAttribute('ip')。服务名称是服务器标签父级中的一个属性,因此您可以通过以下方式获得它:server.parentNode.getAttribute('type')

综上,你可以得到所有的服务器与下面的小宁循环:

for server in yXML.getElementsByTagName('Server'): 
    name = server.getAttribute('name') 
    group = server.parentNode.parentNode.getAttribute('name') 
    ip = server.getAttribute('ip') 
    service = server.parentNode.getAttribute('type') 
    servers.append((name, group, ip, service)) 

记住Zen of Python

平优于嵌套。

分拣机器名

哦,当然,还有一个问题:机器名没有得到很好的排序。然而,这很容易修复:只需对各组进行排序即可。通过下面的行替换以下行

machines = "/".join(machine_set) 
    groups = ", ".join(group_set) 
    services = ", ".join(service_set) 

machines = "/".join(sorted(machine_set)) 
    groups = ", ".join(sorted(group_set)) 
    services = ", ".join(sorted(service_set)) 

在这个例子中,我们整理所有集合,不仅机器名。我敢打赌这也是一个不错的选择。

我知道这个答案不合适很长,但我希望能够解决您的问题并澄清很多要点。

*甚至不需要创建一组组,因为您的示例始终只显示一个组。但我会为了统一而做。