GithubHelp home page GithubHelp logo

aliyun-oss-python-sdk's Introduction

Alibaba Cloud OSS SDK for Python

image

image

image

README of Chinese <https://github.com/aliyun/aliyun-oss-python-sdk/blob/master/README-CN.rst>

Overview

Alibaba Cloud Object Storage Python SDK 2.x. This version is not compatible with the previous version (Version 0.x). The package name is oss2 to avoid conflict with previous versions.

The SDK of this version is dependent on the third-party HTTP library requests and crcmod. Install the SDK following the methods below.

Note:

This version does not contain the osscmd command line tool.

Running environment

Python 2.6(not recommended),2.7,3.3(not recommended),3.4,3.5,3.6

Note:

Python 2.6 is not recommended because it is no longer supported by the Python core team. Do not use Python 3.3.0 or 3.3.1. Refer to Python Issue 16658.

Installing

Install the official release version through PIP (taking Linux as an example):

You can also install the unzipped installer package directly:

Getting started

For more examples, refer to the code under the "examples" directory.

Handling errors

The Python SDK interface will throw an exception in case of an error (see oss2.exceptions sub-module) unless otherwise specified. An example is provided below:

Setup Logging

The following code can set the logging level of 'oss2'.

Testing

First set the required AccessKeyId, AccessKeySecret, endpoint and bucket information for the test through environment variables (Do not use the bucket for the production environment). Take the Linux system for example:

Run the test in the following method:

You can set environment variable to test auth v2:

More resources

Contacting us

License

aliyun-oss-python-sdk's People

Contributors

0xmingyang avatar baiyubin avatar baiyubin2020 avatar cloudfee avatar coderall avatar crhan avatar dozm avatar hangzws avatar huiguangjun avatar jubel-han avatar kkwezard avatar leo23 avatar liyanzhang505 avatar messense avatar mingyangyang avatar qixu001 avatar rockuw avatar wujinhu avatar xkdcc avatar yami avatar yangwanyuan avatar zhuxiaolong37 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aliyun-oss-python-sdk's Issues

在计算签名时,URL中的callback参数没有参与计算

根据说明 https://help.aliyun.com/document_detail/31989.html

如果在URL中携带参数。把callback=[CallBack]或者callback-var=[CallBackVar]作为一个url参数带入请求发送。计算签名CanonicalizedResource时 ,将callback或者callback-var当做一个sub-resource计算在内

而Auth的实现中并没有加入callback以及callback-var

class Auth(object):
    """用于保存用户AccessKeyId、AccessKeySecret,以及计算签名的对象。"""

    _subresource_key_set = frozenset(
        ['response-content-type', 'response-content-language',
         'response-cache-control', 'logging', 'response-content-encoding',
         'acl', 'uploadId', 'uploads', 'partNumber', 'group', 'link',
         'delete', 'website', 'location', 'objectInfo', 'objectMeta',
         'response-expires', 'response-content-disposition', 'cors', 'lifecycle',
         'restore', 'qos', 'referer', 'append', 'position', 'security-token',
         'live', 'comp', 'status', 'vod', 'startTime', 'endTime', 'x-oss-process']
    )

object_exists存在的object报NoSuchKey

在oss存在的文件夹使用object_exists有的key存在有的key不存在,
例如:
bucket.object_exists('xxx/xxx/1/') 结果FALSE 实际存在
bucket.object_exists('xxx/xxx/11/') 结果TRUE 实际存在

fix reuse connection 会使下载大小为零的文件报错

#78

这段代码会使下载大小为零的文件报错。

import oss2

bucket = oss2.Bucket(
    oss2.Auth("xxx", "xxx"),
    "xxx",
    "xxx",
)

bucket.get_object_to_file("xx", "xx")  # 如果oss上的文件大小为零,会报requests.exceptions.StreamConsumedError

因为这里已经做过一次 read,所以 _content_consumed 被设置为True,下次调用 read 就会报错。

而下载文件,在 get_object_to_file 方法中,因为其result.content_length == 0,会再次调用 read 函数,导致报错。

给两个建议

  • 这里的代码去掉,不进行reuse。不是很了解requests的整个机制,不确定这样改靠不靠谱。
  • 还有一种做法是在 get_object_to_file 方法中把 result.content_length == 0result.content_length is None 一样特殊处理。

before put_object i want rename file but got errormessage

before put_object i want rename file but got message

my file upload by python xadmin form post

here is code

def _get_random_fileName(self,name):
        import os, time, random
        # 文件扩展名
        ext = os.path.splitext(name)[1]
        # 文件目录
        d = os.path.dirname(name)
        # 定义文件名,年月日时分秒随机数
        fn = time.strftime('%Y%m%d%H%M%S')
        fn = fn + '%d' % random.randint(0, 100)
        # 重写合成文件名
        name = os.path.join(d, fn + ext)
        if six.PY2:
            name = name.encode('utf-8')
        return name;

    def _save(self, name, content):
        # 为保证django行为的一致性,保存文件时,应该返回相对于`media path`的相对路径。
        target_name = self._get_random_fileName(name)

        content.open()
        content.name = target_name;
        content._file._name = target_name;
        self.bucket.put_object(target_name, content)
        content.close()

        return target_name

{'status': 400, 'details': {'HostId': 'bonday-test.oss-cn-hangzhou.aliyuncs.com', 'Message': 'The specified object is not valid.', 'Code': 'InvalidObjectName', 'RequestId': '58EB68122AE0B9B79576569F', 'ObjectName': '/upload/201704/2017041011101014.png'}}

resumable_upload does not return any response

I'm using resumable_upload but it does not return any response. I was using callback headers so JSON response (returned by OSS requesting the callback of my application server) was expected. I think it's a reasonable feature request. What do you think?

STS 单线程上传文件 经常10053

返回:
{'status': -2, 'details': "RequestError: ('Connection aborted.', error(10053, ''))"}

我一个文件尝试三次上传,只要第一次失败了,后面的一般也会失败。是什么原因?

前端直传时设置了 Callback 在应用服务器接收回调请求时无Body

我使用了服务端设置签名前端直传阿里云oss的文件上传oss。

应用环境如下:

  • 系统: ubuntu 14.04
  • 开发语言:Python 2.7.11/Tornado 4.4.2
  • aliyun-oss-python-sdk latest

其中服务端设置签名及Callback参数如下:

    def get_token(self):
        """
        生成token
        :return:
        """
        logger.info('Aliyun Oss is getting token')
        token_dict = {}
        # 直传条件限制(指定bucket和文件最小最大值)
        condition_list = [['eq', '$bucket', self.bucket_name], ['content-length-range', 0, 10485760]]
        # 回调内容构造
        callback_body = 'filename=${object}&size=${size}&mimeType=${mimeType}'
        # 回调类型构造
        callback_type = 'application/json'

        token_dict['accessid'] = self.accessKeyID
        token_dict['host'] = self.build_post_url(self.endpoint, self.bucket_name)
        token_dict['policy'] = self.build_encode_policy(self.expire_time, condition_list)
        token_dict['signature'] = self.build_signature(self.secretAccessKey, token_dict['policy'])
        token_dict['expire'] = self.expire_time
        token_dict['callback'] = self.bulid_callback(ALIYUN_CALLBACK_URL, callback_body, callback_type)
        raise gen.Return(token_dict)

设置的签名及callback经测试结果都是正确的,前端直传使用的官方示例代码,经测试,可以上传图片,oss中也存在结果,应用服务器也可以接收到回调请求。

回调请求结果如下:

HTTPServerRequest(protocol='http', host='42.121.193.25', method='POST', uri='/v1/file/callback', version='HTTP/1.0', remote_ip='101.200.106.18', headers={'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '79', 'X-Oss-Additional-Headers': '', 'X-Oss-Pub-Key-Url': 'aHR0cHM6Ly9nb3NzcHVibGljLmFsaWNkbi5jb20vY2FsbGJhY2tfcHViX2tleV92MS5wZW0=', 'X-Oss-Tag': 'CALLBACK', 'X-Scheme': 'http', 'Host': '42.121.193.25', 'Content-Md5': 'DrHRNpS3LV5+lGoNrrSabA==', 'X-Real-Ip': '101.200.106.18', 'Connection': 'close', 'X-Oss-Request-Id': '593FBA444F29D0C96BBBCAA0', 'Authorization': 'Fzmmo3aQJkXQq0iu7KWjAwixSyvbUuBb1s6HMRAjGCF7Fzg/pDY5fRSsynS0q6NPsiX483ox2OpM7ZMSdVOZhg==', 'Date': 'Tue, 13 Jun 2017 10:11:16 GMT', 'X-Oss-Owner': '1844361861304115', 'X-Oss-Requester': '1844361861304115', 'X-Oss-Bucket': 'int-long-test-temp', 'User-Agent': 'aliyun-oss-callback', 'X-Oss-Signature-Version': '1.0'})

但是问题来了!可以看到该请求里没有body部分,这与官方文档及示例代码中的不符合,我自己目前没有排查到问题所在,但使用Callback_server.py示例代码进行回调处理时可以接收到回调的body部分。

故想求助下我的Callback处理问题出在何处。

我在处理回调请求的Handler中进行如下操作:

#!/usr/bin/python
# -*- coding: utf-8 -*-
__author__ = 'LexusLee'
"""
该模块进行阿里云直传回调处理
若符合上传条件则返回200
否则删除阿里云文件返回404
"""
from foundation.log import logger
from common.intlong import authenticated, authorized
from serverApp.tools.aliyun import AliyunObject
from serverApp.common.serverAppConfig import ALIYUN_INTERIM_FILE, ALIYUN_FINAL_FILE
from serverApp.common.intlong import RequestHandlerIntlong, ResponseJSON, authenticated
from tornado.gen import coroutine
from tornado.escape import json_decode

import tornado
import base64

aliyun = AliyunObject()

class OssCallbackHandler(RequestHandlerIntlong):
    """
    阿里云上传回调
    """
    @coroutine
    def post(self, **kwargs):
        callback_dict = {}
        filetypes = ['image/jpeg', 'image/jpg', 'image/png']  # 允许上传的文件类型
        file_max_size = 5 * 1024 * 1024  # 允许上传的文件最大值
        try:
            logger.info('进行oss回调')
            # 获得oss服务器回调参数
            origineStr = self.request.body
            # 解析回调的json数据
            callback_param = json_decode(origineStr)

        except Exception as e:
            rsp = ResponseJSON(code=400, description='未收到回调参数')
            logger.error('Get callback error ' + str(e.message))
            raise tornado.gen.Return(self.write(rsp.resultStr()))

        try:
            base64_callback = base64.b64encode(callback_param)
            callback_body = base64_callback['callback_body']
            for line in callback_body.split("&"):
                key, value = line.split("=", 1)  # 分离callback_body仅1次,获得2个数据
                callback_body[key] = value
            # 解析callback字典
            filename = callback_dict['filename'] if 'filename' in callback_dict else None
            size = callback_dict['size'] if 'size' in callback_dict else None
            mimetype = callback_dict['mimeType'] if 'mimeType' in callback_dict else None
        except Exception as e:
            rsp = ResponseJSON(code=500, description='解析回调参数失败')
            logger.error('Parse callback parameters error ' + str(e.message))
            raise tornado.gen.Return(self.write(rsp.resultStr()))

        try:
            # 文件类型不是'image/jpeg', 'image/jpg', 'image/png'则返回403
            if mimetype not in filetypes:
                logger.warning('上传图片格式错误,不能上传格式为' + mimetype + '的图片')
                resp_json = ResponseJSON(403, description='上传图片格式错误')
                aliyun.del_object(ALIYUN_INTERIM_FILE, filename)  # 回滚阿里云
                raise tornado.gen.Return(self.write(resp_json.resultStr()))

            # 若文件大小超过最大值则返回403
            if size > file_max_size:
                logger.warning('上传图片太大,不能上传大于5m的图片')
                resp_json = ResponseJSON(403, description='上传图片太大,不能上传大于5m的图片')
                aliyun.del_object(ALIYUN_INTERIM_FILE, filename)  # 回滚阿里云
                raise tornado.gen.Return(self.write(resp_json.resultStr()))
        except Exception as e:
            rsp = ResponseJSON(code=403, description='文件上传不符合条件')
            logger.error('Invalid file ' + str(e.message))
            raise tornado.gen.Return(self.write(rsp.resultStr()))

        rsp = ResponseJSON(code=200)
        logger.info('文件符合条件,上传阿里云成功')
        raise tornado.gen.Return(self.write(rsp.resultStr()))

origineStr = self.request.body 这行代码中接收到了oss回调post的请求,请求结果如上 Request所示,但是无法获取request中的body部分,故无法进行后续图片格式、图片大小等限制。

get_object方法有严重的效率问题

一个80MB的文件 内网下载. 需要耗时 4分钟
期间cpu会占用到100%
如果用get_object_to_file 只要两秒就能下载完成

import arrow
import qbtrade as qb

b = qb.util.get_oss_bucket('qbtrade')
key = 'quant-historical/source-pubsub.tick/2016/11/01/btc_t:exchange.xtc.okcom'
s = arrow.now()
y = b.get_object(key)
buf = y.read()
print('elapse', arrow.now() - s)

print('content size ', len(buf))
s = arrow.now()
b.get_object_to_file(key, '/tmp/largefile')
print('elapse', arrow.now() - s)
 > python test_oss.py
config_path ['/home/tyz/.qbconf', '/etc/qbconf']
set env by region alihk
elapse 0:04:06.504253
content size  77268874
elapse 0:00:01.547841

问题出在这一行
https://github.com/aliyun/aliyun-oss-python-sdk/blob/master/oss2/http.py#L87

网上找了下解答
http://stackoverflow.com/questions/3055477/how-slow-is-pythons-string-concatenation-vs-str-join

Cannot upload file exceeds 2GB on Windows 32 bit Python

It is because requests.utils.super_len() finds len attribute in our adapter classes and len() only return int (4 bytes) on Windows 32 bit Python build.

We will fix this by removing len method in adapter classes, instead we use property len, which is also recognizable by super_len() to avoid len().

mimetypes guess_type is slow on Windows

有时候read_windows_registry需要耗费3秒左右的时间。下面是cProfile的一个输出

Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.004    0.004    3.957    3.957 test.py:3(<module>)
        1    0.000    0.000    3.667    3.667 api.py:555(init_multipart_upload)
        1    0.000    0.000    3.620    3.620 utils.py:70(set_content_type)
        1    0.000    0.000    3.620    3.620 utils.py:61(content_type_by_name)
        1    0.000    0.000    3.620    3.620 mimetypes.py:274(guess_type)
        1    0.000    0.000    3.619    3.619 mimetypes.py:347(init)
        1    0.452    0.452    3.619    3.619 mimetypes.py:228(read_windows_registry)
     5445    2.158    0.000    2.158    0.000 {_winreg.OpenKey}
      847    0.548    0.001    0.548    0.001 {_winreg.QueryValueEx}
     5439    0.008    0.000    0.460    0.000 mimetypes.py:241(enum_types)
     5439    0.453    0.000    0.453    0.000 {_winreg.EnumKey}

文档bug

  • README里的注释里说key是storage.txt,实际上是story.txt
  • readthedocs里没有加上最新的StsAuth

能否开放HTTPAdapter中max_retries参数,偶尔网络异常时,bucket的操作没有自动重试

class Session(object):
"""属于同一个Session的请求共享一组连接池,如有可能也会重用HTTP连接。"""
def init(self):
self.session = requests.Session()

    psize = defaults.connection_pool_size
    self.session.mount('http://', requests.adapters.HTTPAdapter(pool_connections=psize, pool_maxsize=psize))
    self.session.mount('https://', requests.adapters.HTTPAdapter(pool_connections=psize, pool_maxsize=psize))

能否开放一下HTTPAdapter的配置,现在我除了改源码,没办法从外部修改重试次数,感谢各位大神

image.py requires Pillow

from PIL import image

but PIL is not a standard python library. In setup.py, it should requires Pillow for python2

oss2 怎样上传一个文件夹

你好,

请问怎样在oss2里面上传整个文件夹?我发现OSS Browser可以做到,但是oss2我尝试了bucket.put_object_from_file(), 如果指定文件夹会抛异常。在oss2 bucket中没有发现其它可用的接口。请指教。

Li

某些文件无法上传,报Broken pipe

如题。

一个APK文件,文件可以正常使用。
使用put_object_from_file方法。

一开始以为是文件太大了,然而尝试了更大的文件,是可以上传成功的。
试了分片上传,也是不行。
把文件压缩后再上传,可以成功。
尝试上传QQ的APK,可以成功。
使用oss客户端上传,可以成功。

apk.zip请解压

max_keys参数无效

通过测试发现list_objects 这个函数是支持分页的,但oss2.ObjectIterator函数的max_keys是无效的。

unconfigured logging used

unconfigured logging used in auth.py, resumble.py, task_queue.py.
This lead to bucket key info reveled.
temporary working around:

ch = logging.StreamHandler()
ch.setLevel(logging.FATAL)
logging.root.addHandler(ch)

并发进行分块上传时最终合并出来的文件会出现错乱

并发N个线程进行大文件分块上传,最终合并出来的文件有些分块的位置错开了(文件大小是和源文件一样的)。

调试时对比了一下,bucket.upload_part 时 part_number 的顺序是对的。

但是SizedFileAdapter传入的file_obj在读的时候没有对位置进行seek,在并发上传的时候应该保证不了会按序读取。

请问一下能提供一个分块并发上传的demo看一下吗?

resumable download 不支持大文件

oss 一个5G 的大文件,用ossutil 下载是可以的,但用resumable download 就不行:

try:
            #self._bucket.get_object_to_file(fpath, dstpath)
            obj = oss2.resumable_download(self._bucket, fpath, dstpath,
                    store=oss2.ResumableStore(root='/tmp'),
                    multiget_threshold=32*1024*1024,
                    part_size=4*1024*1024,
                    num_threads=4)
            print 'download ok, and obj is:'
            print obj
        except oss2.exceptions.OssError as e:
            ret["status"] = "Error"
            ret["errmsg"] = str(e)

结果:

download ok, and obj is:
None
{'status': 'OK', 'end-time': 'Tue Mar 27 14:49:29 2018', 'start-time': 'Tue Mar 27 14:49:29 2018', 'file-size': 0, 'elapsed-time': 0.11, 'speed': '0.0MB/s', 'errmsg': ''}

给我一个空文件!

2.X SDK 下载速度过慢

调用Python 0.46 SDK 中的 osscmd.cmd_get 接口下载文件, 平均速度可以达到 12.69MB/s, 但是使用Python 2.X SDK 的API , 最高下载速度不超过5MB/s, 平均下载速度3MB/s, 请问是什么原因?

环境: win7, python3.6, 主机在华北2, OSS在北京, 测试文件大小为289MB,

# 创建Bucket对象,所有Object相关的接口都可以通过Bucket对象来进行
bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name)
key = 'win7.zip'
filename = 'download.zip'

"""
断点续传下载
"""
# 断点续传下载
begin = time.time()
oss2.resumable_download(bucket, key, filename, num_threads=7)
end = time.time()
print (u'耗时: %.3f(s)\n' % (end - begin))
# 清理文件
os.remove(filename)

`get_object()` 不支持请求字符串回源

在 bucket 启用镜像回源并且激活携带请求字符串回源的情况下,该 sdk 并不会正确地传递请求字符串到源站,实际测试中,请求参数被格式化为 URL 编码导致回源失败.

例如:

prefix/filename?param=value  ==> prefix/filename%3Fparam%3Dvalue

修复:
jubel-han@149a02e

可以认为Headers中的ETag就是MD5吗?

为了避免文件重复上传,在上传前,调用get_object_meta()
虽然获取不到Content-MD5, 但是可以获取到ETag
发现该ETag刚好与文件MD5相同,这是巧合吗?
另外ETag使用了双引号,是有什么作用吗?

    HTTP/1.1 200 OK
    x-oss-request-id: 559CC9BDC755F95A64485981
    Date: Wed, 29 Apr 2015 05:21:12 GMT
    ETag: "5B3C1A2E053D763E1B002CC607C5A0FE"
    Last-Modified: Fri, 24 Feb 2012 06:07:48 GMT
    Content-Length: 344606
    Connection: keep-alive
    Server: AliyunOSS

谢谢!

获取文件的同时获取 meta

get_object 直接获取文件流;
head_object 只获取 meta 信息;

为了获取一个文件同时获得 meta 信息,要发送两个请求。有没有一个方法可以一次请求即得到文件,又得到 meta?

bucket.complete_multipart_upload()自定义报头MD5总是返回校验错误

def calculate_file_md5(file_name, block_size=64 * 1024):
    """计算文件的MD5
    :param file_name: 文件名
    :param block_size: 计算MD5的数据块大小,默认64KB
    :return 文件内容的MD5值
    """
    with open(file_name, 'rb') as f:
        md5 = hashlib.md5()
        while True:
            data = f.read(block_size)
            if not data:
                break
            md5.update(data)
    return base64.b64encode(md5.digest())

def calculate_data_md5(data):
    """计算数据的MD5
    :param data: 数据
    :return MD5值
    """
    md5 = hashlib.md5()
    md5.update(data)
    return base64.b64encode(md5.digest())

这个是sdk里面的MD5校验本地文件的sdk函数,
分片上传bucket.upload_part(key, upload_id, part_number, data, headers={'Content-MD5': encodeMD5})分片上传时用calculate_data_md5()计算的分片md5是没问题的,当执行完分片上传后,合并分片时用
encodeMD5 = calculate_file_md5(filename, block_size=blockSize) 计算好本地文件的MD5值
bucket.complete_multipart_upload(key, upload_id, parts, headers={'Content-MD5': encodeMD5})
当执行到这里的时候总是会返回错误InvalidDigest, 400

如果是我的代码出的问题,希望给出个complete_multipart_upload, MD5校验的example,谢谢

sts 的例子已经跑不起来了

例子中使用了 do_action 的方法,但是python 3.6 pip 安装的最新版 aliyun-python-sdk-sts 并不存在这个方法,我换成了 do_action_with_exception 才能够跑起来。但是有 deprecated 及其他警告。是以下几条。

python3.6/site-packages/urllib3/contrib/pyopenssl.py:46: DeprecationWarning: OpenSSL.rand is deprecated - you should use os.urandominstead
  import OpenSSL.SSL


python3.6/site.py:165: DeprecationWarning: 'U' mode is deprecated
  f = open(fullname, "rU")


sys:1: ResourceWarning: unclosed <socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.2.207', 62845), raddr=('118.178.62.22', 80)>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.