FASTDFS PYTHON [-] Error: response size not match, expect: 105, actual: 105 解决

fdfs_client-py1.2.6.zip 是 fastdfs 的python版的客户端api,现在最新的版本是1.2.6,而fastdfs文件系统一直持续更新,而相应的客户端python客户端一直没有更新,为什么呢?因为写fastdfs的作者余大不会python,python版的客户端是其他人贡献出来的,所以一直没有更新。这就造成了不兼容的问题。
这个不兼容问题体现在:获得fdfs的组信息,例如这个报错:<[-] Error: response size not match, expect: 105, actual: 105>就是低版本python 客户端不兼容高版本的fastdfs而引发的,高版本的fastdfs一些内部结构体已经扩充。
fdfs_client-py1.2.6.zip基本上支持各种上传和下载,对获取存储节点数据信息存在不兼容问题。如果用不到此功能可以忽略改报错。
我使用fastdfs的版本是5.05,要想python版的api支持该版本,只能在原有1.2.6版本的基础上进行代码级修改,使其适应5.05通讯结构。一下就是我的具体做法:

  1. unzip fdfs_client-py1.2.6.zip 进入目录
  2. vim fdfs_client/tracker_client.py
#替换原始的Group_info类
class Group_info(object):
    def __init__(self):
        self.group_name            = ''
        self.totalMB               = ''
        self.freeMB                = ''
        self.trunk_freeMB          = ''
        self.count                 = 0
        self.storage_port          = 0
        self.store_http_port       = 0
        self.active_count          = 0
        self.curr_write_server     = 0
        self.store_path_count      = 0
        self.subdir_count_per_path = 0
        self.curr_trunk_file_id    = 0
        self.fmt                   = '!%ds 11Q' % (FDFS_GROUP_NAME_MAX_LEN + 1)
        return None

    def __str__(self):

        s = 'Group information:\n'
        s += '\tgroup name = %s\n' % self.group_name
        s += '\ttotal disk space = %s\n' % self.totalMB
        s += '\tdisk free space = %s\n' % self.freeMB
        s += '\ttrunk free space = %s\n' % self.trunk_freeMB
        s += '\tstorage server count = %d\n' % self.count
        s += '\tstorage port = %d\n' % self.storage_port
        s += '\tstorage HTTP port = %d\n' % self.store_http_port
        s += '\tactive server count = %d\n' % self.active_count
        s += '\tcurrent write server index = %d\n' % self.curr_write_server
        s += '\tstore path count = %d\n' % self.store_path_count
        s += '\tsubdir count per path = %d\n' % self.subdir_count_per_path
        s += '\tcurrent trunk file id = %d\n' % self.curr_trunk_file_id
        return s

    def set_info(self, bytes_stream):
        (group_name, totalMB, freeMB, trunk_freeMB, self.count, self.storage_port, \
         self.store_http_port, self.active_count, self.curr_write_server, \
         self.store_path_count, self.subdir_count_per_path, self.curr_trunk_file_id) \
        = struct.unpack(self.fmt, bytes_stream)
        try:
            self.group_name = group_name.strip('\x00')
            self.freeMB = appromix(freeMB, FDFS_SPACE_SIZE_BASE_INDEX)
            self.totalMB = appromix(totalMB, FDFS_SPACE_SIZE_BASE_INDEX)
            self.trunk_freeMB = appromix(trunk_freeMB, FDFS_SPACE_SIZE_BASE_INDEX)
        except ValueError:
            raise DataError('[-] Error disk space overrun, can not represented it.')

    def get_fmt_size(self):
        return struct.calcsize(self.fmt)

更改的依据,fastdfs5.05原始代码对该通讯协议的描述:
FASTDFS PYTHON [-] Error: response size not match, expect: 105, actual: 105 解决_第1张图片
python struct.unpack操作提取是和该结构体一一对应的(懂得c语言的同学应该知道怎么回事)

#替换原始的Storage_info类
class Storage_info(object):
    def __init__(self):
        self.status = 0
        self.id = ''
        self.ip_addr = ''
        self.domain_name = ''
        self.src_id = ''
        self.version = ''
        self.join_time = datetime.fromtimestamp(0).isoformat()
        self.up_time = datetime.fromtimestamp(0).isoformat()
        self.totalMB = ''
        self.freeMB = ''
        self.upload_prio = 0
        self.store_path_count = 0
        self.subdir_count_per_path = 0
        self.curr_write_path = 0
        self.storage_port = 23000
        self.storage_http_port = 80
        self.alloc_count = 0
        self.current_count = 0
        self.max_count = 0
        self.total_upload_count = 0
        self.success_upload_count = 0
        self.total_append_count = 0
        self.success_append_count = 0
        self.total_modify_count = 0
        self.success_modify_count = 0
        self.total_truncate_count = 0
        self.success_truncate_count = 0
        self.total_setmeta_count = 0
        self.success_setmeta_count = 0
        self.total_del_count = 0
        self.success_del_count = 0
        self.total_download_count = 0
        self.success_download_count = 0
        self.total_getmeta_count = 0
        self.success_getmeta_count = 0
        self.total_create_link_count = 0
        self.success_create_link_count = 0
        self.total_del_link_count = 0
        self.success_del_link_count = 0
        self.total_upload_bytes = 0
        self.success_upload_bytes = 0
        self.total_append_bytes = 0
        self.success_append_bytes = 0
        self.total_modify_bytes = 0
        self.success_modify_bytes = 0
        self.total_download_bytes = 0
        self.success_download_bytes = 0
        self.total_sync_in_bytes = 0
        self.success_sync_in_bytes = 0
        self.total_sync_out_bytes = 0
        self.success_sync_out_bytes = 0
        self.total_file_open_count = 0
        self.success_file_open_count = 0
        self.total_file_read_count = 0
        self.success_file_read_count = 0
        self.total_file_write_count = 0
        self.success_file_write_count = 0
        self.last_source_sync = datetime.fromtimestamp(0).isoformat()
        self.last_sync_update = datetime.fromtimestamp(0).isoformat()
        self.last_synced_time = datetime.fromtimestamp(0).isoformat()
        self.last_heartbeat_time = datetime.fromtimestamp(0).isoformat()
        self.if_trunk_server = ''
        #fmt = |-status(1)-ipaddr(16)-domain(128)-srcipaddr(16)-ver(6)-52*8-|
        self.fmt = '!B 16s 16s 128s 16s 6s 10Q 4s4s4s 42Q?'

    def set_info(self, bytes_stream):
        (self.status, self.id, ip_addr, domain_name, self.src_id,\
         version, join_time, up_time, totalMB, freeMB, \
         self.upload_prio, self.store_path_count, \
         self.subdir_count_per_path, self.curr_write_path, \
         self.storage_port, self.storage_http_port, \
         self.alloc_count, self.current_count, self.max_count, \
         self.total_upload_count, self.success_upload_count, \
         self.total_append_count, self.success_append_count, \
         self.total_modify_count, self.success_modify_count, \
         self.total_truncate_count,self.success_truncate_count, \
         self.total_setmeta_count, self.success_setmeta_count, \
         self.total_del_count,    self.success_del_count, \
         self.total_download_count,self.success_download_count, \
         self.total_getmeta_count, self.success_getmeta_count, \
         self.total_create_link_count, self.success_create_link_count, \
         self.total_del_link_count, self.success_del_link_count, \
         self.total_upload_bytes, self.success_upload_bytes, \
         self.total_append_bytes, self.total_append_bytes, \
         self.total_modify_bytes, self.success_modify_bytes, \
         self.total_download_bytes, self.success_download_bytes, \
         self.total_sync_in_bytes, self.success_sync_in_bytes, \
         self.total_sync_out_bytes, self.success_sync_out_bytes, \
         self.total_file_open_count, self.success_file_open_count, \
         self.total_file_read_count, self.success_file_read_count, \
         self.total_file_write_count, self.success_file_write_count, \
         last_source_sync, last_sync_update, last_synced_time, \
         last_heartbeat_time, self.if_trunk_server,) \
          = struct.unpack(self.fmt, bytes_stream)
        try:
            self.ip_addr = ip_addr.strip('\x00')
            self.domain_name = domain_name.strip('\x00')
            self.version = version.strip('\x00')
            self.totalMB = appromix(totalMB, FDFS_SPACE_SIZE_BASE_INDEX)
            self.freeMB = appromix(freeMB, FDFS_SPACE_SIZE_BASE_INDEX)
        except ValueError, e:
            raise ResponseError('[-] Error: disk space overrun, can not represented it.')
        self.join_time = datetime.fromtimestamp(join_time).isoformat()
        self.up_time   = datetime.fromtimestamp(up_time).isoformat()
        self.last_source_sync = datetime.fromtimestamp(last_source_sync).isoformat()
        self.last_sync_update = datetime.fromtimestamp(last_sync_update).isoformat()
        self.last_synced_time = datetime.fromtimestamp(last_synced_time).isoformat()
        self.last_heartbeat_time = \
           datetime.fromtimestamp(last_heartbeat_time).isoformat()
        return True

    def __str__(self):
        '''Transform to readable string.'''

        s  = 'Storage information:\n'
        s += '\tip_addr = %s (%s)\n' % (self.ip_addr, parse_storage_status(self.status))
        s += '\thttp domain = %s\n' % self.domain_name
        s += '\tversion = %s\n' % self.version
        s += '\tjoin time = %s\n' % self.join_time
        s += '\tup time = %s\n' % self.up_time
        s += '\ttotal storage = %s\n' % self.totalMB
        s += '\tfree storage = %s\n' % self.freeMB
        s += '\tupload priority = %d\n' % self.upload_prio
        s += '\tstore path count = %d\n' % self.store_path_count
        s += '\tsubdir count per path = %d\n' % self.subdir_count_per_path
        s += '\tstorage port = %d\n' % self.storage_port
        s += '\tstorage HTTP port = %d\n' % self.storage_http_port
        s += '\tcurrent write path = %d\n' % self.curr_write_path
        s += '\tsource ip_addr = %s\n' % self.ip_addr
        s += '\tif_trunk_server = %d\n' % self.if_trunk_server
        s += '\ttotal upload count = %ld\n' % self.total_upload_count
        s += '\tsuccess upload count = %ld\n' % self.success_upload_count
        s += '\ttotal download count = %ld\n' % self.total_download_count
        s += '\tsuccess download count = %ld\n' % self.success_download_count
        s += '\ttotal append count = %ld\n' % self.total_append_count
        s += '\tsuccess append count = %ld\n' % self.success_append_count
        s += '\ttotal modify count = %ld\n' % self.total_modify_count
        s += '\tsuccess modify count = %ld\n' % self.success_modify_count
        s += '\ttotal truncate count = %ld\n' % self.total_truncate_count
        s += '\tsuccess truncate count = %ld\n' % self.success_truncate_count
        s += '\ttotal delete count = %ld\n' % self.total_del_count
        s += '\tsuccess delete count = %ld\n' % self.success_del_count
        s += '\ttotal set_meta count = %ld\n' % self.total_setmeta_count
        s += '\tsuccess set_meta count = %ld\n' % self.success_setmeta_count
        s += '\ttotal get_meta count = %ld\n' % self.total_getmeta_count
        s += '\tsuccess get_meta count = %ld\n' % self.success_getmeta_count
        s += '\ttotal create link count = %ld\n' % self.total_create_link_count
        s += '\tsuccess create link count = %ld\n' % self.success_create_link_count
        s += '\ttotal delete link count = %ld\n' % self.total_del_link_count
        s += '\tsuccess delete link count = %ld\n' % self.success_del_link_count
        s += '\ttotal upload bytes = %ld\n' % self.total_upload_bytes
        s += '\tsuccess upload bytes = %ld\n' % self.success_upload_bytes
        s += '\ttotal download bytes = %ld\n' % self.total_download_bytes
        s += '\tsuccess download bytes = %ld\n' % self.success_download_bytes
        s += '\ttotal append bytes = %ld\n' % self.total_append_bytes
        s += '\tsuccess append bytes = %ld\n' % self.success_append_bytes
        s += '\ttotal modify bytes = %ld\n' % self.total_modify_bytes
        s += '\tsuccess modify bytes = %ld\n' % self.success_modify_bytes
        s += '\ttotal sync_in bytes = %ld\n' % self.total_sync_in_bytes
        s += '\tsuccess sync_in bytes = %ld\n' % self.success_sync_in_bytes
        s += '\ttotal sync_out bytes = %ld\n' % self.total_sync_out_bytes
        s += '\tsuccess sync_out bytes = %ld\n' % self.success_sync_out_bytes
        s += '\ttotal file open count = %ld\n' % self.total_file_open_count
        s += '\tsuccess file open count = %ld\n' % self.success_file_open_count
        s += '\ttotal file read count = %ld\n' % self.total_file_read_count
        s += '\tsuccess file read count = %ld\n' % self.success_file_read_count
        s += '\ttotal file write count = %ld\n' % self.total_file_write_count
        s += '\tsucess file write count = %ld\n' % self.success_file_write_count
        s += '\tlast heartbeat time = %s\n' % self.last_heartbeat_time
        s += '\tlast source update = %s\n' % self.last_source_sync
        s += '\tlast sync update = %s\n' % self.last_sync_update
        s += '\tlast synced time = %s\n' % self.last_synced_time
        return s

    def get_fmt_size(self):
        return struct.calcsize(self.fmt)

更改的依据,fastdfs5.05原始代码对该通讯协议的描述:
FASTDFS PYTHON [-] Error: response size not match, expect: 105, actual: 105 解决_第2张图片

3。 vim fdfs_client/utils.py

#替换方法appromix,新方法如下
def appromix(size, base = 0):
    '''Conver bytes stream size to human-readable format.
    Keyword arguments:
    size: int, bytes stream size
    base: int, suffix index
    Return: string
    '''
    multiples = 1024
    if size < 0:
        raise ValueError('[-] Error: number must be non-negative.')
    if size < multiples:
        return '{0:d}{1}'.format(size, SUFFIX[base])
    for suffix in SUFFIX[base:]:
        if size < multiples:
            return '{0:.2f}{1}'.format(size,suffix)
        size = size / float(multiples)
    raise ValueError('[-] Error: number too big.')

5。保存修改内容,执行 python setup.py install。 调用相关方法就不会报错了。注意:以上编辑python文件一定要注意缩进问题,否则运行脚本会报语法错误。
下面链接我修改过的fdfs_client-py代码,大家可以下载安装使用,我称之为python的fastdfs 1.2.8版本。
fastdfs python client 1.2.8

你可能感兴趣的:(fastdfs)