第十二章:互联网-urllib.request:网络资源访问--创建定制协议处理器

12.2.7 创建定制协议处理器
urllib.request提供了对HTTP(S)、FTP和本地文件访问的内置支持。为了增加对其他URL类型的支持,可以注册另外的协议处理器。例如,为了支持指向远程NFS服务器上任意文件的URL,而不需要用户在访问文件之前先装再路径,可以创建一个派生BaseHandler的类,并包含一个nfs_open()方法。
协议特定的open()方法有一个参数,即Request实例,它会返回一个对象,这个对象有一个read()方法来读取数据,一个info()方法来返回响应首部,还有一个geturl()方法返回所读取文件的具体URL。要满足这些需求,一种简单的办法是创建urllib.response.addinfourl的一个实例,然后把首部、URL和打开的文件句柄传入它的构造函数。

import io
import mimetypes
import os
import tempfile
from urllib import request
from urllib import response

class NFSFile:

    def __init__(self,tempdir,filename):
        self.tempdir = tempdir
        self.filename = filename
        with open(os.path.join(tempdir,filename),'rb') as f:
            self.buffer = io.BytesIO(f.read())

    def read(self,*args):
        return self.buffer.read(*args)

    def readline(self,*args):
        return self.buffer.readline(*args)

    def close(self):
        print('\nNFSFile:')
        print('  unmounting {}'.format(
            os.path.basename(self.tempdir)))
        print('  when {} is closed'.format(
            os.path.basename(self.filename)))

class FauxNFSHandler(request.BaseHandler):

    def __init__(self,tempdir):
        self.tempdir = tempdir
        super().__init__()

    def nfs_open(self,req):
        url = req.full_url
        directory_name,file_name = os.path.split(url)
        server_name = req.host
        print('FauxNFSHandler simulating mount:')
        print('  Remote path: {}'.format(directory_name))
        print('  Server     : {}'.format(server_name))
        print('  Local path : {}'.format(
            os.path.basename(tempdir)))
        print('  Filename   : {}'.format(file_name))
        local_file = os.path.join(tempdir,file_name)
        fp = NFSFile(tempdir,file_name)
        content_type = (
            mimetypes.guess_type(filename)[0] or
            'application/octet-stream'
            )
        stats = os.stat(local_file)
        size = stats.st_size
        headers = {
            'Content-type':content_type,
            'Content-length':size,
            }
        return response.addinfourl(fp,headers,req.get_full_url())

if __name__ == '__main__':
    with tempfile.TemporaryDirectory() as tempdir:
        # Populate the temporary fiel for the simulation.
        filename = os.path.join(tempdir,'file.txt')
        with open(filename,'w',encoding='utf-8') as f:
            f.write('Contents of file.txt')

        # Construct an opener with our NFS handler
        # and register it as the default opener.
        opener = request.build_opener(FauxNFSHandler(tempdir))
        request.install_opener(opener)

        # Open the file through a URL.
        resp = request.urlopen(
            'nfs://remote_server/path/to/the/file.txt'
            )
        print()
        print('READ CONTENTS:',resp.read())
        print('URL          :',resp.geturl())
        print('HEADERS:')
        for name,value in sorted(resp.info().items()):
            print(' {:<15} = {}'.format(name,value))
        resp.close()

FauxNFSHandler和NFSFile类可以打印消息,以展示已给真实实现会在哪里增加装载(mount)和卸载(unmount)调用。由于这指示一个模拟,所以只向FauxNFSHandler提供了一个临时目录名,它会在这个目录中查找所有文件。
运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值