在python中获取类型错误

时间:2016-05-19 10:27:07

标签: python class error-handling

我在python中使用基于类的服务,每当我想使用它时我都会收到错误。无法弄清楚原因。

#!/usr/bin/python
# -*- coding: utf-8 -*-

from xml.dom import minidom
from pysimplesoap.client import SoapClient
from pysimplesoap.helpers import sort_dict

MEDIA_ROOT = '/User/sunand/documents/resumes/'
parser = ResumeParser()
names = parser.get_names(MEDIA_ROOT)
print names


class ParserClient(SoapClient):

""" Extends the soap client to encode the response with utf-8 encoding.
"""

def wsdl_call(
    self,
    method,
    *args,
    **kwargs
    ):
    """ Override wsdl_call method to make sure unmarshall is not called.
    """

    operation = self.get_operation(method)

    # get i/o type declarations:

    inp = operation['input']
    header = operation.get('header')
    if 'action' in operation:
        self.action = operation['action']

    # construct header and parameters

    if header:
        self.__call_headers = sort_dict(header, self.__headers)
    (method, params) = self.wsdl_call_get_params(method, inp,
            *args, **kwargs)

    response = self.call(method, *params)
    return response

def send(self, method, xml):
    """ Overrides the send method to get the actual xml content.
    """

    content = super(ParserClient, self).send(method, xml)
    self.result = content
    return content
class ResumeParser(object):

""" Connects to the Resume Parser's XML api to get parsed data.
"""

def __init__(self, simple=True, timeout=60):
    """ Initializes the ResumeParser class.
    """

    self.wsdl = \
        'http://jobsite.onlineresumeparser.com/rPlusParseResume.asmx?WSDL'
    self.secret = 'my-secret-key'  # Enter key here
    self.encoding = 'base64'
    self.simple = simple
    self.client = ParserClient(wsdl=self.wsdl, timeout=timeout)
    self.names = []

def get_file_content(self, file_path):
    """ Return the encoded content for the given file.
    """

    file_obj = open(os.path.abspath(file_path), 'r')
    content = file_obj.read().encode(self.encoding)
    file_obj.close()

    return content

def get_names(self, path):
    """
    Given a path to a folder that contains resume files this method
    will parse the resumes and will return the names of the candidates
    as a list.
    """

    opt = os.path
    resumes = [opt.join(path, r) for r in os.listdir(path)
               if opt.isfile(opt.join(path, r))]

    # Parse information for each resume.

    for resume in resumes:
        try:
            xml_data = self.get_xml(resume)
            name = self.get_name_from_xml(xml_data)
            if name:
                self.names.append(name)
        except Exception, err:

                # print name

            print 'Error parsing resume: %s' % str(err)

    return list(set(self.names))

def get_name_from_xml(self, data):
    """ Returns the full name from the xml data given.
    """

    xmldata = minidom.parseString(data)
    name = xmldata.getElementsByTagName('CANDIDATE_FULL_NAME')
    name = name[0].childNodes[0].data.title()

    return name

def get_xml(self, filepath):
    """ Fetches and returns the xml for the given file from the api.
    """

    filename = os.path.basename(filepath)

    extension = os.path.splitext(filepath)[1]

    base64 = self.get_file_content(filepath)

    filedata = {
        'B64FileZippedContent': base64,
        'FileName': filename,
        'InputType': extension,
        'UserID': 1,
        'secretKey': self.secret,
        }

    get = \
        (self.client.GetSimpleXML if self.simple else self.client.getHRXML)
    get(**filedata)

    return self.process_raw_xml()

def process_raw_xml(self, data=None):
    """ Processes and returns the clean XML.
    """

    raw = (data if data else self.client.result)
    parsed = minidom.parseString(raw)
    result = parsed.getElementsByTagName('GetSimpleXMLResult')[0]
    text_node = result.childNodes[0]
    data = text_node.data.encode('UTF-8')

    return data

运行代码后,我收到错误消息 TypeError:wsdl_call_get_params()得到一个意外的关键字参数'secretKey'

我做错了什么?

1 个答案:

答案 0 :(得分:1)

您似乎错误地覆盖了wsdl_call

首先,我们可以看到SoapClient(您在ParserClient中扩展)有一个__getattr__函数,用于获取SoapClient的伪属性。

def __getattr__(self, attr):
    "Return a pseudo-method that can be called"
    if not self.services: # not using WSDL?
        return lambda self=self, *args, **kwargs: self.call(attr,*args,**kwargs)
    else: # using WSDL:
        return lambda *args, **kwargs: self.wsdl_call(attr,*args,**kwargs)

您可以看到此函数正在使用wsdl_call来帮助它将函数映射到未知属性。

导致问题的特定伪方法在您的代码中(或似乎是):

filedata = {
    'B64FileZippedContent': base64,
    'FileName': filename,
    'InputType': extension,
    'UserID': 1,
    'secretKey': self.secret, # <-- the secretKey key word argument
    }

get = \
    (self.client.GetSimpleXML if self.simple else self.client.getHRXML)
get(**filedata)
# here client is an instance of your `ParserClient` (and `SoapClient`).

上面这一点让我花了一些时间来追查。有了完整的堆栈跟踪,我会发现它更快。请求帮助时,请务必在将来发布堆栈跟踪(如果有)。

如何解决此问题

  • 提供GetSimpleXMLgetHRXML的具体实施。这将解决眼前的问题,但不会解决更大的问题。
  • 重写wsdl_call

重写的代码段应检查method参数的值,并执行您想要的操作,或委派给SoapClient实现。

例如

def wsdl_call(self, method, *args, **kwargs):
    if method == "some_method":
        return self._my_wsdl_call(method, *args, **kwargs)
    else:
        return super(ParserClient, self).wsdl_call(method, *args, **kwargs)

def _my_wsdl_call(self, method, *args, **kwargs):
    ...