阿里云的 Python SDK 是真的烂啊, 想起个 aliyunpythonsdksucks 项目组, 然后把他们的 sdk 封装一下 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
LeoQ
V2EX    Python

阿里云的 Python SDK 是真的烂啊, 想起个 aliyunpythonsdksucks 项目组, 然后把他们的 sdk 封装一下

  •  
  •   LeoQ
    LeoQuote 2019-01-22 17:00:12 +08:00 6916 次点击
    这是一个创建于 2504 天前的主题,其中的信息可能已经有所发展或是发生改变。

    槽多无口, 里面的接口还有 v20140815 , 所有的 class 看起来都一样, 一样的长, 一样的难以理解

    举个例子 CreateOnlineDataBaseTaskRequest

    # 阿里云的代码 from aliyunsdkcore.request import RpcRequest class CreateOnlineDatabaseTaskRequest(RpcRequest): def __init__(self): RpcRequest.__init__(self, 'Rds', '2014-08-15', 'CreateOnlineDatabaseTask','rds') def get_ResourceOwnerId(self): return self.get_query_params().get('ResourceOwnerId') def set_ResourceOwnerId(self,ResourceOwnerId): self.add_query_param('ResourceOwnerId',ResourceOwnerId) def get_MigrateTaskId(self): return self.get_query_params().get('MigrateTaskId') def set_MigrateTaskId(self,MigrateTaskId): self.add_query_param('MigrateTaskId',MigrateTaskId) def get_DBName(self): return self.get_query_params().get('DBName') def set_DBName(self,DBName): self.add_query_param('DBName',DBName) def get_ResourceOwnerAccount(self): return self.get_query_params().get('ResourceOwnerAccount') def set_ResourceOwnerAccount(self,ResourceOwnerAccount): self.add_query_param('ResourceOwnerAccount',ResourceOwnerAccount) def get_ClientToken(self): return self.get_query_params().get('ClientToken') def set_ClientToken(self,ClientToken): self.add_query_param('ClientToken',ClientToken) def get_OwnerAccount(self): return self.get_query_params().get('OwnerAccount') def set_OwnerAccount(self,OwnerAccount): self.add_query_param('OwnerAccount',OwnerAccount) def get_DBInstanceId(self): return self.get_query_params().get('DBInstanceId') def set_DBInstanceId(self,DBInstanceId): self.add_query_param('DBInstanceId',DBInstanceId) def get_CheckDBMode(self): return self.get_query_params().get('CheckDBMode') def set_CheckDBMode(self,CheckDBMode): self.add_query_param('CheckDBMode',CheckDBMode) def get_OwnerId(self): return self.get_query_params().get('OwnerId') def set_OwnerId(self,OwnerId): self.add_query_param('OwnerId',OwnerId) 
    # 我想要的代码 class DatabaseTask: def __init__(self, **kwargs): self.migrate_task = migrate_task self.db_name = db_name self.resource_owner = resource_owner self.token = token self.check_db_mode = check_db_mode def run(): # make some request if __name__ == '__main__': new_task = DatabaseTask(migrate_task=1, db_name='some_db', resource_owner='some_user', token='some_token', check_db_mode='some_mode') result = new_task.run() result.fetch() 

    为什么不写成 一个 DatabaseTask 对象, 对象有几个属性值 Instance_id 等 ,然后再调用 DatabaseTask.create()

    这些 set 和 get 的方法, 不就是实现了 python 的属性值吗?

    我这里想问一下大家, 如果我这么做了, 会收到律师函吗?

    34 条回复    2019-01-23 22:13:46 +08:00
    glasslion
        1
    glasslion  
       2019-01-22 17:19:35 +08:00   2
    这种代码一看就是 先有 Java 的 SDk, 实现 Python SDK 时直接照搬了 Java 的实现。 这种行为虽然挺恶心的, 但毕竟是最节省开发资源的做法,也只能忍了 。

    Google 的 Python SDK 一样大量这种代码。


    抛开代码风格的问题, 阿里云 Python SDK 早期的代码质量极差, 连培训班水平都不如。 目前的质量已经比以前好太多了。
    https://github.com/aliyun/aliyun-openapi-python-sdk/issues/43
    www5070504
        2
    www5070504  
       2019-01-22 17:21:55 +08:00   3
    支持 这种带有 java “风味”的 python 代码是 python 中的毒瘤
    qq976739120
        3
    qq976739120  
       2019-01-22 17:24:07 +08:00   1
    我之前看他们的代码以为是我功力不够的原因....原来是他们写的查,汗!
    wuhaochen999
        4
    wuhaochen999  
       2019-01-22 17:43:33 +08:00   1
    get set 有啥问题
    Cbdy
        5
    Cbdy  
       2019-01-22 18:08:59 +08:00 via Android   1
    估计是直接根据 Java SDK 代码用编译器编译成 Python 代码的(代码生成)吧,其他语言类似。这样只需要维护一份 Java 代码即可
    wusphinx
        6
    wusphinx  
       2019-01-22 18:10:11 +08:00   1
    在保证代码正确性的前提下,代码不够 pythonic 还是可以接受的
    alvin666
        7
    alvin666  
       2019-01-22 18:13:19 +08:00 via Android   1
    妈耶
    这代码要人命啊
    janxin
        8
    janxin  
       2019-01-22 18:15:22 +08:00   1
    支持,每次用 Python 的 SDK 用的想死
    aldslvda
        9
    aldslvda  
       2019-01-22 19:05:58 +08:00   1
    java 味太浓
    dongqihong
        10
    dongqihong  
       2019-01-22 19:32:18 +08:00   1
    这是自动化生成的接口代码。。。
    shaodamao
        11
    shaodamao  
       2019-01-22 19:50:50 +08:00   1
    之前用过他们的 python sdk,sdk 代码应该是根据 api 生成的。
    可以用 aliyunsdkcore.request 中的 CommonRequest,自己封装了个通用的方法,将就用一下 orz
    KgM4gLtF0shViDH3
        12
    KgM4gLtF0shViDH3  
       2019-01-22 20:26:01 +08:00   1
    这明显是自动生成的代码。。和机器人较真干啥。
    iorilu
        13
    iorilu  
       2019-01-22 22:18:37 +08:00   1
    这个 sdk 是干啥用的
    Faiz555
        14
    Faiz555  
       2019-01-22 23:03:28 +08:00
    用过阿里云的短信 SDK,调用的时候感觉巨恶心
    luozic
        15
    luozic  
       2019-01-22 23:49:45 +08:00 via iPhone
    这种要么是基于 Java 生成,要么直接根据 OAI 类似 swagger 的规范直接一把生成,不分 java 还是啥
    qingtangsdk
        16
    qingtangsdk  
       2019-01-22 23:59:57 +08:00   6
    亲们,大家好,我是阿里云 SDK 的研发 GG,看到吐槽就赶紧诚惶诚恐地过来啦^_^。首先感谢大家对阿里云 Python SDK 的关注,这里跟大家十分十分(* 1024 )诚恳地道歉,Python SDK 没有按照 Python 的编码规范设计,我们没做好,给大家造成了不好的体验,对不起!

    为了解决好这个这个问题呢,我们阿里云 SDK 研发团队正在抓紧时间编写阿里云 Python SDK 的第二版,目前是刚起步,项目代码在这里: https://github.com/aliyun/alibabacloud-python-sdk-v2 请大家过目。亲们可以在: https://github.com/aliyun/alibabacloud-python-sdk-v2/issues 这里吐槽,我们会抓紧时间改进哦!

    亲们的批评就是我们改进的动力,为此我们会不断努力,感谢对阿里云的关心!
    lxml
        17
    lxml  
       2019-01-23 00:26:16 +08:00 via Android
    想起了金山云的 SDK,fork 自 aws 的,然后大家表示读不懂代码,宁愿调用我的 http 接口都不愿意自己去接入。
    niubee1
        18
    niubee1  
       2019-01-23 01:26:42 +08:00
    在国内的项目组里呢一般都只有边缘人和实习生才会干搞 SDK 这类事情, 质量差是很自然的事情
    incompatible
        19
    incompatible  
       2019-01-23 02:40:53 +08:00
    v20140815 有什么问题? 公有云产品的 API 必须向下兼容,即便某天发布了 v2020xxxx,先前的 v20140815 也是要永久保留的。
    SDK 里 client 与 request 各司其职,request 负责封装 API 的参数; client 负责从 request 取参数、做签名、拼 url 发请求、解析返回值。且各个产品的各个 API 都 follow 此 pattern,学一次就会用所有产品的 API 了。
    你自己定义的 DatabaseTask 相比之下并没看出有什么优点,仅仅是满足了你自己的偏好而已。
    busyboy
        20
    busyboy  
       2019-01-23 07:54:59 +08:00
    我已经很知足了,比部分云厂商的好很多
    susucoolsama
        21
    susucoolsama  
       2019-01-23 08:08:12 +08:00 via iPhone
    @qingtangsdk 这个回复应该是妹子客服回复的吧,这文笔不像是程序 gg....
    est
        22
    est  
       2019-01-23 08:58:20 +08:00 via Android
    代码烂不是槽点,依赖一个老掉牙的加密库才是
    glasslion
        23
    glasslion  
       2019-01-23 10:18:01 +08:00
    @dongqihong
    @bestkayle
    @luozic
    @Cbdy
    你们高估阿里云了, 这代码就是让实习生抄出来的
    Feiox
        24
    Feiox  
       2019-01-23 10:51:21 +08:00   1
    相比之下 微软的 azure python sdk 如同神赐一般
    guanhui07
        25
    guanhui07  
       2019-01-23 14:25:16 +08:00
    好像 java
    LeoQ
        26
    LeoQ  
    OP
       2019-01-23 15:42:20 +08:00
    @incompatible 谢谢你的不留情面的批评, 可能是我孤陋寡闻了, 但是国外的云厂商, 我在 aws 的 sdk https://github.com/boto/botocore/tree/develop/botocore 里没有发现版本的印记, 在 azure 的 sdk 里, 版本的印记还存在, 但是一些最近有修改的模块已经没有了版本的文件夹 https://github.com/Azure/azure-sdk-for-python .

    这说明带时间的版本已经不是最佳实践, azure 也在尝试改变这一点, 完全可以通过 SDK 的主版本进行控制

    带时间的版本我认为也确实不友好, 比如 20140817 版本和 20180704 版本兼容吗? 用户是不清楚的 , 如果是类似 0.0.1 和 3.0.0 , 那么用户自己就有感觉, 这个代码可能是不兼容了,再参阅一下文档, 确实是不兼容的, 那么, 要么改代码, 要么安装低版本的 sdk.

    我给出的版本确实是满足了自己的偏好, 但我认为是确实比之前的容易理解的, 把 get set 改为对对象的属性值操作

    既然可以
    ```
    new_task = DatabaseTask()
    new_task.owner = 'me'
    print(new_task.owner)
    ```

    那么为什么要
    ```
    new_task = DatabaseTask()
    new_task.set_owner('me')
    print(new_task.get_owner('me'))
    ```

    而且属性值也天生支持动态获取, 动态设置

    ```
    new_task.setattr('owner','me')
    new_task.getattr('owner')
    ```
    如果是函数的话, 没有办法做到动态的.

    我认为这在 python 中是更友好的一种调用方法, 你觉得呢?
    LeoQ
        27
    LeoQ  
    OP
       2019-01-23 15:47:04 +08:00
    @est 新的已经不依赖了, 感恩
    est
        28
    est  
       2019-01-23 16:18:34 +08:00
    @LeoQ 那还挺不错。不过已经被我们用一个 5 行的 python 函数+urllib 给代替了。
    LeoQ
        30
    LeoQ  
    OP
       2019-01-23 16:38:04 +08:00
    @abmin521 https://github.com/Azure/azure-sdk-for-python/blob/master/azure-mgmt-dns/azure/mgmt/dns/models.py
    确实是有, 但是你看一下这里, 在 models 层做了一个快捷方式, 默认情况下, 是调 v2018_03_01_preview.models 的, 对于开发者来说, 如果版本的需求, 是可以不用在代码里体现 v2018_03_01_preview 这些冗长的字符的.

    这些快捷方式, 阿里做了吗? 没有.
    LeoQ
        31
    LeoQ  
    OP
       2019-01-23 16:40:36 +08:00
    incompatible
        32
    incompatible  
       2019-01-23 20:41:38 +08:00
    @LeoQ

    关于 API 的向下兼容:并非指的是 v2020xxxx 要兼容 v20140815 的功能,而是说即便发布了 v2020xxxx 后,v20140815 依然可用并且行为不变。 对于调用方来说,升级 api 版本或者 sdk 版本都是非常 critical 的事,在升级过程中,校验 sdk 或 api 的版本兼容性是必不可少的步骤。当然如你所说,sdk 版本和 api 版本强绑定是个糟糕的设计。

    属性和 setter 之间的取舍,你看一下阿里 sdk 的源码,它是在 setter 里把 params 放到了父类的一个 dictionary 里了。另外基于它代码中有 add_query_param()的字样,我推测除了 query params 应该还有 body params、header_params、这些是基于 api metadata 生成 sdk 的 request 就固定下来的,如果不用 setter 的方式就需要额外的 metadata 来描述一个 param 的位置到底是在 query、body 还是 header 中。

    最后关于动态设置 request 的属性,我自己是阿里云 ecs/rds/slb 等产品 java sdk 的重度用户,其实不太明白为什么有“动态设置属性”这种需求。你有什么场景是必须要动态设置属性的嘛?
    LeoQ
        33
    LeoQ  
    OP
       2019-01-23 21:36:09 +08:00
    我最后提到动态属性的意思是, 属性值是有好处的, 代码风格上会看起来更简单易读.

    Python 和 Java 类似, 也可以有 setter 和 getter 函数

    不一样的是, python 还有 property 装饰器, 加入这个装饰器, 就可以正常使用 student.age del(student.age)这种做法了
    ```
    class Student(object):
    def __init__(self):
    self._age = None

    @property
    def age(self):
    return self._age

    @age.setter
    def age(self, age):
    if isinstance(age, int):
    self._age = age
    return
    if isinstance(age, str) and age.isdigit():
    age = int(age)
    self._age = age
    else:
    raise ValueError("age is illegal")

    @age.deleter
    def age(self):
    del self._age
    ```
    我还顺着翻到了它的 base 类 https://github.com/aliyun/aliyun-openapi-python-sdk/blob/master/aliyun-python-sdk-core/aliyunsdkcore/request.py 到了 base 依然是有着大量的普通的 set_XXX / set_XXX 方法.

    而我因为他们代码都是 set_XXX 的, 我也得写这样冗长的代码, 为什么不改成上面的那种呢?

    我的意思是, python 里有很多的语法糖可以做这些事情, 但是阿里云的 sdk 都没有用到.
    Trim21
        34
    Trim21  
       2019-01-23 22:13:46 +08:00 via Android
    看着真像自动生成的…
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3573 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 04:18 PVG 12:18 LAX 20:18 JFK 23:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86