2012-07-12 4 views
0

클래스를 인스턴스화 한 다음 토네이도 웹 템플릿으로 전달했습니다. 두 함수 모두 목록을 반환하지만 클래스 자체를 반복 가능한 객체로 만드는 데는 뭔가 빠져 있습니다. 나는 그것이 근본적으로 내가 잘못하고있는 것이 아닌가 걱정된다. REST API 호출을 만들고, 반환 된 XML을 구문 분석하고 일부 데이터를 webapp에 반환합니다.클래스를 반복자로 인스턴스화

API 호출 :

class GetVMList: 

    def __init__(self): 
     user = 'contoso\\administrator' 
     password = "apassword" 
     url = "http://scspf:8090/SC2012/VMM/Microsoft.Management.Odata.svc/VirtualMachines?$filter=VMMServer%20eq%20'scvmm'" 

     passman = urllib2.HTTPPasswordMgrWithDefaultRealm() 
     passman.add_password(None, url, user, password) 
     # create the NTLM authentication handler 
     auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman) 

     # create and install the opener 
     opener = urllib2.build_opener(auth_NTLM) 
     urllib2.install_opener(opener) 

     # retrieve the result 
     self.response = urllib2.urlopen(url) 
     self.data = self.response.read() 

    def name(self): 
     dom = parseString(self.data) 
     raw_xml = dom.getElementsByTagName('d:Name') 
     clean_xml = [] 
     clean_data = [] 
     for i in raw_xml: 
      clean_xml.append(i.toxml()) 
     for i in clean_xml: 
      clean_data.append(i.replace('<d:Name>', '').replace('</d:Name>', '')) 
     return clean_data 

    def os(self): 
     dom = parseString(self.data) 
     raw_xml = dom.getElementsByTagName('d:OperatingSystem') 
     clean_xml = [] 
     clean_data = [] 
     for i in raw_xml: 
      clean_xml.append(i.toxml()) 
     for i in clean_xml: 
      clean_data.append(i.replace('<d:OperatingSystem>', '').replace('</d:OperatingSystem>', '')) 
     return clean_data 

인스턴스화 :

class ListHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.render('temp/search.html', data='') 

    def post(self): 
     vm_list = GetVMList() 
     self.render('temp/search.html', data=vm_list) 

그리고 템플릿이 포함되어 있습니다

{% for vm in data %} 
<li>{{ vm.name }} running {{ vm.os }}</li> 
{% end %} 

오류는 다음과 같습니다 TypeError: iteration over non-sequence 여기에 코드입니다. 나는 내 수업에서 __iter__을 사용해야한다고 생각 하겠지만 그것이 어떻게 작동하는지 정확히 이해하고 있는지 확신 할 수 없다.

+1

'__iter __()'메소드가 보이지 않기 때문에 물론'GetVMList' 클래스의 인스턴스는 반복 가능하지 않습니다. 또한 클래스 이름을'GetVMList()'가 아니라'VMList()'로 지정하면 안됩니다 ... 클래스는 동사가 아닌 명사입니다. 마지막으로, 클래스가 아닌 반복자/생성기가 실제로 필요합니다. 또한 VM의 * list *에는 개별 VM의 속성 인'name' 또는'os'가 없지만 이름이나 OS를 지정할 VM을 지정하는 방법이 없습니다 의. 당신은 심하게 디자인을 재고 할 필요가 있습니다. – kindall

+0

반환해야 할 항목은 무엇입니까? 예 : 'GetVMList()에서 x에 대해 : print x' 무엇을 인쇄해야합니까? – mgilson

+0

@kindall 고맙습니다. 이것은 정확하게 조언 유형입니다. 이것은 제가 많이 알고있는 것이 아닙니다. 당신의 충고는 정말 도움이됩니다. 나는'__iter__'을 내가 필요한 것으로 생각했지만 그것을 구현하는 방법을 확신하지 못했습니다. – Danielscottt

답변

1

내 조언은 다음과 같습니다

  1. 은 하나의 VM에 대한 정보를 저장하는 클래스 VM를 만듭니다. 그 __init__ 각 VM에 대해 저장하고 인스턴스의 속성으로 설정하려는 정보를해야합니다. VM에 대한 데이터와 함께 진행하기 위해 실제 코드가 필요하지 않은 경우 메서드를 작성할 필요가 없으므로 collections.namedtuple을 사용할 수 있습니다.

  2. 사용자, 암호 및 URL이 주어진 경우 생성자로 VM 인스턴스를 생성합니다. 이 결과는있는 그대로 반복 할 수 있으며 필요하면 정규 목록으로 쉽게 변환 (list()에 전달)하거나 VM 이름을 OS에 매핑하거나 그 반대로 매핑하는 사전을 만드는 데 사용할 수 있습니다.

(이 코드는 테스트되지 않았습니다) :

class VM(object): 
    def __init__(self, name, os): 
     self.name = name 
     self.os = os 

def getVMs(user, password, URL): 
    passman = urllib2.HTTPPasswordMgrWithDefaultRealm() 
    passman.add_password(None, url, user, password) 
    auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman) 
    urllib2.install_opener(urllib2.build_opener(auth_NTLM)) 
    dom = parseString(urllib2.urlopen(url).read()) 
    for vmnode in dom.getElementsByTagName('d:VM') # the tag representing a VM 
     name = vmnode.getElementsByTagName('d:Name')[0] # get name of current VM 
     name = name.replace('<d:Name>', '').replace('</d:Name>', '') 
     os = vmnode.getElementsByTagName('d:OperatingSystem')[0] # same for OS 
     os = os.replace('<d:OperatingSystem>', '').replace('</d:OperatingSystem>', '')) 
     yield VM(name, os) 

... 당신은 또한 당신의 VM 이름과 OS, 또는 전체 VM을위한 XML에 대한 XML 객체하지만,이 샘플 구현에만 않는 줄 수 이름과 OS를 문자열로 지정하십시오.

(.이 빈 문자열로 XML 태그를 교체 의지하지 않고 DOM 노드의 내용을 얻을 수있는 더 나은 방법이 있습니다,하지만 지금은 그렇게 할 시간이 없어)

를 호출 :

user = r"contoso\administrator" 
pass = "apassword" 
url = ("http://scspf:8090/SC2012/VMM/Microsoft.Management.Odata.svc" 
     "/VirtualMachines?$filter=VMMServer%20eq%20'scvmm'") 

vmlist = list(getVMs(user, pass, url)) 

또는 단지 중간 목록을 저장하지 않고 각 VM에 대한 정보를 인쇄하려면 :

for vm in getVMs(user, pass, url): 
    print vm.name, vm.os 

또는 VM 인스턴스에 이름 사전을 구축을 (DICT 함축을 가지고 파이썬의 최신 버전을 가정) :

vmdict = {vm.name: vm for vm in getVMs(user, pass, url)} 

발전기 모델을 사용하면 호출자가 최대한 유연합니다.그 호출자가 당신이라면, 그것은 당신의 삶을 편하게 해줄 것입니다.

+0

'yield '는 _definitely_ 내가 배울 필요가있는 개념입니다. 환상적으로 작동합니다. 다시 한 번 감사드립니다. – Danielscottt

+0

예, 'yield'는 많은 문제에 놀랍도록 간단한 해결책입니다. – kindall

관련 문제