最近用Python中的suds访问webservice,由于之前发布的webservice有问题,最先采用soaplib来进行发布,后来发现其已经不更新不维护了,已经改为rpclib(官方地址:http://github.com/arskom/rpclib)进行后续开发,但在rpclib的readme中,介绍了rpclib已经更名为spyne,并将持续进行更新,所以最后就选用spyne进行开发了,基于web框架Flask。
在不断变换发布方式的过程中,一直使用suds来进行访问,但是发布的URL不变。结果发现,在服务器上访问URL失败,而用其它URL则是成功。困惑中。。。。最后查之,是因为suds使用了filecache,所以访问的是第一次发布的URL,第一次发布的URL需要进行schema校验,而服务器不能访问外网导致的。
主要代码如下:
def open(self, url):
"""
Open an XML document at the specified I{url}.
First, the document attempted to be retrieved from
the I{object cache}. If not found, it is downloaded and
parsed using the SAX parser. The result is added to the
cache for the next open().
@param url: A document url.
@type url: str.
@return: The specified XML document.
@rtype: I{Document}
"""
cache = self.cache()
id = self.mangle(url, 'document')
d = cache.get(id)
if d is None:
d = self.download(url)
cache.put(id, d)
self.plugins.document.parsed(url=url, document=d.root())
return d
这是根据文件ID来获取文件内容的代码,首先从文件cache中获取,若获取不到则从网络获取。其中cache对象即为ObjectCache,继承自FileCache,而FileCache的初始化代码为:
def __init__(self, location=None, **duration):
"""
@param location: The directory for the cached files.
@type location: str
@param duration: The cached file duration which defines how
long the file will be cached. A duration=0 means forever.
The duration may be: (months|weeks|days|hours|minutes|seconds).
@type duration: {unit:value}
"""
if location is None:
location = os.path.join(tmp(), 'suds')
self.location = location
self.duration = (None, 0)
self.setduration(**duration)
self.checkversion()
其中tmp()方法的定义为:
def gettempdir():
"""Accessor for tempfile.tempdir."""
global tempdir
if tempdir is None:
_once_lock.acquire()
try:
if tempdir is None:
tempdir = _get_default_tempdir()
finally:
_once_lock.release()
return tempdir
def _get_default_tempdir():
"""Calculate the default directory to use for temporary files.
This routine should be called exactly once.
We determine whether or not a candidate temp dir is usable by
trying to create and write to a file in that directory. If this
is successful, the test file is deleted. To prevent denial of
service, the name of the test file must be randomized."""
namer = _RandomNameSequence()
dirlist = _candidate_tempdir_list()
flags = _text_openflags
for dir in dirlist:
if dir != _os.curdir:
dir = _os.path.normcase(_os.path.abspath(dir))
# Try only a few names per directory.
for seq in xrange(100):
name = namer.next()
filename = _os.path.join(dir, name)
try:
fd = _os.open(filename, flags, 0o600)
try:
try:
with _io.open(fd, 'wb', closefd=False) as fp:
fp.write(b'blat')
finally:
_os.close(fd)
finally:
_os.unlink(filename)
return dir
except (OSError, IOError) as e:
if e.args[0] != _errno.EEXIST:
break # no point trying more names in this directory
pass
raise IOError, (_errno.ENOENT,
("No usable temporary directory found in %s" % dirlist))
至此,已经完全清楚,是找一个可写的目录,然后测试是否可读可写,并返回该目录。文件就写在响应的目录下。耗费了半个下午的时间,终于找出问题,Mark一下。