自游客 https://zuk.pw/index.php 撒欢儿去 Fri, 01 Nov 2019 05:57:38 +0800 zh-CN hourly 1 https://wordpress.org/?v=5.3 https://zuk.pw/wp-content/uploads/2018/01/avatars-150x150.png 自游客 https://zuk.pw/index.php 32 32 ubuntu 耳机没有声音 https://zuk.pw/index.php/2018/08/141.html https://zuk.pw/index.php/2018/08/141.html#respond Wed, 08 Aug 2018 00:22:09 +0000 https://zuk.pw/?p=141 安装选项卡

输入下面命令安装pavucontrol:

sudo apt install pavucontrol

配置

打开选项卡

pavucontrol

16.04

“回放”–>系统下面的选项–>内置音频模拟立体声

“输出设备”–>port:headphone(unplugged) 模拟耳机

18.04

配置->内置音频 修改为 模拟立体声 输出

输出设备->Port 修改为 模拟耳机

]]>
https://zuk.pw/index.php/2018/08/141.html/feed 0
ubuntu 18.04 修改时区命令 https://zuk.pw/index.php/2018/08/140.html https://zuk.pw/index.php/2018/08/140.html#respond Sat, 04 Aug 2018 00:33:50 +0000 https://zuk.pw/?p=140

运行如下命令:

sudo tzselect

然后选择亚洲Asia,继续选择中国China,最后选择北京Beijing。


然后创建时区软链

sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

现在看下时间,是不是已经正常了呢。

]]>
https://zuk.pw/index.php/2018/08/140.html/feed 0
每天自动获取 Bing 壁纸 https://zuk.pw/index.php/2018/04/131.html https://zuk.pw/index.php/2018/04/131.html#respond Sun, 15 Apr 2018 14:14:13 +0000 https://zuk.pw/?p=131 自从换了 mac 之后,直观的感觉是桌面变的更空旷了(本来我就不喜欢在桌面放东西)。所以,壁纸成了装点桌面的唯一工具。正好 Bing 的背景图片每天都会换一张,并且几乎每张图片都让人感觉非常大气,所以就萌生了用 Bing 图片做壁纸的想法(话说让我知道 Bing 每天都会换背景图,还是因为之前做 Kratos 的时候有小伙伴提出网页的背景图能不能调用 Bing 的接口 《每天自动获取 Bing 壁纸》 )。我先看了一下 Apple Store 里面有没有这种 App,果不其然还真有,但是这价格的话,emmmmm 算了还是自己整吧。

利弊分析

Bing 的图片有 4 种像素,分别是 1920×1200、1920×1080、800×480、400×240,而 mac 可以支持到 2880 x 1800,所以在视觉上看着壁纸不是非常的清晰的(系统自带的壁纸是 5120 × 3684)。

这里制作的自动化脚本是每次开机启动的,如果一天开机好几次的话,脚本会自带检测是否已经下载过图片,从而不会重复下载。

战前准备

  • MAC 中自带的 Automator
  • bing-wallpaper 脚本
  • 充满智慧的大脑 《每天自动获取 Bing 壁纸》

战斗开始

1、首先我们知道 Bing 图片是有一个接口的,也就是 https://cn.bing.com/HPImageArchive.aspx?format=js&n=1 ,他的主要内容如下,这里我们需要的是第 7 行 url,也就是图片的地址,所以在脚本中只要拉这个 url 地址即可实现需求。

{
    images: [
        {
            startdate: "20180315",
            fullstartdate: "201803151600",
            enddate: "20180316",
            url: "/az/hprichbg/rb/WolongPanda_ZH-CN10957042976_1920x1080.jpg",
            urlbase: "/az/hprichbg/rb/WolongPanda_ZH-CN10957042976",
            copyright: "卧龙国家级自然保护区的大熊猫,中国四川 (© Lynn M. Stone/Minden Pictures)",
            copyrightlink: "http://www.bing.com/search?q=%E5%A4%A7%E7%86%8A%E7%8C%AB&form=hpcapt&mkt=zh-cn",
            quiz: "/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20180315_WolongPanda%22&FORM=HPQUIZ",
            wp: false,
            hsh: "6fa3921773323a6e7f0f45447e548f91",
            drk: 1,
            top: 1,
            bot: 1,
            hs: [ ]
        }
    ],
    tooltips: {
        loading: "正在加载...",
        previous: "上一个图像",
        next: "下一个图像",
        walle: "此图片不能下载用作壁纸。",
        walls: "下载今日美图。仅限用作桌面壁纸。"
    }
}

2、bing-wallpaper 是一个可以从 Bing 下载当天最新图片并将其保存到目录的脚本。

#!/usr/bin/env bash
# shellcheck disable=SC1117

readonly SCRIPT=$(basename "$0")
readonly VERSION='0.4.0'
readonly RESOLUTIONS=(1920x1200 1920x1080 800x480 400x240)

usage() {
cat <<EOF
Usage:
  $SCRIPT [options]
  $SCRIPT -h | --help
  $SCRIPT --version
Options:
  -f --force                     Force download of picture. This will overwrite
                                 the picture if the filename already exists.
  -s --ssl                       Communicate with bing.com over SSL.
  -q --quiet                     Do not display log messages.
  -n --filename <file name>      The name of the downloaded picture. Defaults to
                                 the upstream name.
  -p --picturedir <picture dir>  The full path to the picture download dir.
                                 Will be created if it does not exist.
                                 [default: $HOME/Pictures/bing-wallpapers/]
  -r --resolution <resolution>   The resolution of the image to retrieve.
                                 Supported resolutions: ${RESOLUTIONS[*]}
  -w --set-wallpaper             Set downloaded picture as wallpaper (Only mac support for now).
  -h --help                      Show this screen.
  --version                      Show version.
EOF
}

print_message() {
    if [ ! "$QUIET" ]; then
        printf "%s\n" "${1}"
    fi
}

# Defaults
PICTURE_DIR="$HOME/Pictures/bing-wallpapers/"
RESOLUTION="1920x1080"

# Option parsing
while [[ $# -gt 0 ]]; do
    key="$1"

    case $key in
        -r|--resolution)
            RESOLUTION="$2"
            shift
            ;;
        -p|--picturedir)
            PICTURE_DIR="$2"
            shift
            ;;
        -n|--filename)
            FILENAME="$2"
            shift
            ;;
        -f|--force)
            FORCE=true
            ;;
        -s|--ssl)
            SSL=true
            ;;
        -q|--quiet)
            QUIET=true
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        -w|--set-wallpaper)
            SET_WALLPAPER=true
            ;;
        --version)
            printf "%s\n" $VERSION
            exit 0
            ;;
        *)
            (>&2 printf "Unknown parameter: %s\n" "$1")
            usage
            exit 1
            ;;
    esac
    shift
done

# Set options
[ $QUIET ] && CURL_QUIET='-s'
[ $SSL ]   && PROTO='https'   || PROTO='http'

# Create picture directory if it doesn't already exist
mkdir -p "${PICTURE_DIR}"

# Parse bing.com and acquire picture URL(s)
read -ra urls < <(curl -sL $PROTO://www.bing.com | \
    grep -Eo "url:'.*?'" | \
    sed -e "s/url:'\([^']*\)'.*/$PROTO:\/\/bing.com\1/" | \
    sed -e "s/\\\//g" | \
    sed -e "s/\([[:digit:]]*x[[:digit:]]*\)/$RESOLUTION/")

for p in "${urls[@]}"; do
    if [ -z "$FILENAME" ]; then
        filename=$(echo "$p"|sed -e "s/.*\/\(.*\)/\1/")
    else
        filename="$FILENAME"
    fi
    if [ $FORCE ] || [ ! -f "$PICTURE_DIR/$filename" ]; then
        print_message "Downloading: $filename..."
        curl $CURL_QUIET -Lo "$PICTURE_DIR/$filename" "$p"
    else
        print_message "Skipping: $filename..."
    fi
done

if [ $SET_WALLPAPER ]; then
    /usr/bin/osascript<<END
tell application "System Events" to set picture of every desktop to ("$PICTURE_DIR/$filename" as POSIX file as alias)
END
fi

3、在脚本的第 39-40 行,是设置图片的保存位置以及图片的像素。这里默认的是最高像素,保存的位置为 /Pictures/bing-wallpapers/ 这个文件夹中,下图是这段时间我电脑里拉到的一些图片。

《每天自动获取 Bing 壁纸》

4、将修改好的脚本添加到 Automator 的工作流程中,左边选择“运行 Shell 脚本”

《每天自动获取 Bing 壁纸》

5、将保存好的工作流程添加到“登录项”中,从而实现开机自动运行

《每天自动获取 Bing 壁纸》

6、最后,我们设置桌面背景,添加壁纸所在的文件夹,然后再勾选更改图片的频率为每天

《每天自动获取 Bing 壁纸》

]]>
https://zuk.pw/index.php/2018/04/131.html/feed 0
十年程序员用眼告诉你2018PHP不一样 https://zuk.pw/index.php/2018/02/124.html https://zuk.pw/index.php/2018/02/124.html#respond Sun, 25 Feb 2018 08:24:36 +0000 https://zuk.pw/?p=124 《十年程序员用眼告诉你2018PHP不一样》

PHP从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js 、GO和Python不断地在挑战PHP的地位。这些技术的推动者非常热衷于唱衰PHP,PHP语言的未来在哪里?PHP程序员当如何应对未来的变革?

作为老牌的Web后端编程语言,PHP在全球市场占有率非常高,仅次于Java,从各个招聘网站的数据上来看PHP开发的职位非常多,薪资水平也非常不错。实际在中小企业、互联网创业公司PHP的市场地位是高于Java的。Java在超大型企业、传统软件行业、金融领域优势更大。目前来看 Node.js、 GO 、 Python 、 Ruby 等语言还难以企及PHP和Java。

PHP语言之所以能有今天的地位,得益于PHP语言设计者一直遵从实用主义,将技术的复杂性隐藏在底层。PHP语言入门简单,容易掌握,程序健壮性好,不容易出现像Java 、 C++ 等其他语言那样复杂的问题,如内存泄漏和 Crash,跟踪调试相对轻松很多。

PHP官方提供的标准库非常强大,各种功能函数都能在官方的标准库中找到,包括MySQL、Memcache、Redis、GD图形库、CURL、XML、JSON等等,免除了开发者到处找库的烦恼。PHP 的文档非常棒,每个函数都有详细的说明和使用示例。第三方类库和工具、代码、项目也很丰富。开发者可以快速、高效地使用PHP编写开发各类软件。

到目前为止市面上仍然没有出现比PHP更简单易用的编程语言。所以PHP的前景还是很广阔的,与其纠结于编程语言的选择,不如好好地深入学习使用PHP 。

作为一个资深的PHP开发者,在技术上给各位PHP程序几点未来的建议,希望对大家有所帮助。

1. Composer

第一点就要提Composer,自从Composer出现后,PHP的依赖管理可以变得非常简单。程序内依赖一些类库和框架,直接使用Composer引入即可,通过使用composer update安装依赖的包。解决了过去加载外部库的各种难题。

Composer也有国内镜像,速度非常快。现在绝大部分PHP开源的项目都提供了Composer的支持,建议大家在项目中使 Composer来解决PHP代码包管理的问题,不要再使用下载源码、手工include的原始方法。

2. PHP7

PHP7版本对Zend引擎做了大量修改,大幅提升了PHP语言的性能,使用PHP7可以使你的程序性能瞬间翻倍。即使是WordPress这样重量级的软件运行在PHP7都能有上千QPS,相当于一台服务器每天就能处理8000万次请求。

使用PHP7,做好MySQL优化,使用Memcache和Redis进行加速,这套技术架构完全可以应对相当大规模的系统。除了某些亿级用户的平台之外,一般规模的系统完全没有压力。

3. PSR

PSR是PHPFramework Interop Group 组织制定的PHP语言开发规范,约定了很多方面的规则,如命名空间、类名规范、编码风格标准、Autoload、公共接口等。现在已经成为PHP技术社区事实上的标准了。很多知名的PHP框架和类库都遵守了PSR规范。PHP开发者应当学习掌握PSR规范,在开发程序时应当尽量遵循PSR规范。

4. Swoole

2017年PHP还局限于做Web网站吗?No,如果你还不知道Swoole,赶快去了解一下吧。Swoole的口号是重新定义PHP语言,Swoole是一个异步并行的通信引擎,作为PHP的扩展来运行。Node.js的异步回调Swoole有,Go语言的协程Swoole也有,这完全颠覆了对PHP的认知。使用Swoole PHP 可以实现常驻内存的Server程序,可以实现TCP、UDP异步网络通信的编程开发。

过去PHP只能做一个Web网站,现在使用Swoole可以做Java 、C++才能实现的通信服务,比如WebSocket即使通信、聊天、推送服务器、RPC远程调用服务、网关、代理、游戏服务器等。如果你想用PHP做点Web系统之外的东西,Swoole是最好的选择。

5. Laravel

最近几年最火热的PHP框架,官网号称是为Web艺术家设计的框架,可见这套框架有多优雅。Laravel提供的功能模块丰富,API设计简洁,表达力强。而且它的社区非常活跃,代码贡献者众多,第三方的插件非常多,生态系统相当繁荣。

Laravel底层使用了很多symfony2组件,通过composer实现了依赖管理。如果还在纠结使用什么PHP框架,不如选择 Laravel。Laravel提供的命令行工具基于symfony.console实现,功能强大,集成了各种项目管理、自动生成代码的功能。

6. Phar

PHP5.3之后支持了类似Java的jar包,名为phar。用来将多个PHP文件打包为一个文件。这个特性使得PHP也可以像Java一样方便地实现应用程序打包和组件化。一个应用程序可以打成一个Phar包,直接放到PHP-FPM中运行。

配合Swoole,可以在命令行下执行php server.phar 一键启动服务器。PHP的代码包可以用Phar打包成组件,放到Swoole的服务器容器中去加载执行。

]]>
https://zuk.pw/index.php/2018/02/124.html/feed 0
Redis 和 Memcached 的区别 https://zuk.pw/index.php/2018/02/118.html https://zuk.pw/index.php/2018/02/118.html#comments Wed, 07 Feb 2018 14:42:59 +0000 https://zuk.pw/?p=118 《Redis 和 Memcached 的区别》

说到redis就会联想到memcached,反之亦然。了解过两者的同学有那么个大致的印象:redis与memcached相比,比仅支持简单的key-value数据类型,同时还提供list,set,zset,hash等数据结构的存储;redis支持数据的备份,即master-slave模式的数据备份;redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用等等,这似乎看起来redis比memcached更加牛逼一些,那么事实上是不是这样的呢?存在即合理,我们来根据几个不同点来一一比较一下。

网络IO模型

memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe传递给worker线程,进行读写IO,网络层使用libevent封装的事件库,多线程模型可以发挥多核作用,但是引入了cache coherency和锁的问题,比如:memcached最常用的stats命令,实际memcached所有操作都要对这个全局变量加锁,进行技术等工作,带来了性能损耗。

redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现了epoll, kqueue和select,对于单存只有IO操作来说,单线程可以将速度优势发挥到最大,但是redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作,单线程模型施加会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞的。

数据支持类型

memcached使用key-value形式存储和访问数据,在内存中维护一张巨大的HashTable,使得对数据查询的时间复杂度降低到O(1),保证了对数据的高性能访问。

正如开篇所说:redis与memcached相比,比仅支持简单的key-value数据类型,同时还提供list,set,zset,hash等数据结构的存储;详细可以翻阅《Redis内存使用优化与存储》

内存管理机制

对于像Redis和Memcached这种基于内存的数据库系统来说,内存管理的效率高低是影响系统性能的关键因素。传统C语言中的malloc/free函数是最常用的分配和释放内存的方法,但是这种方法存在着很大的缺陷:首先,对于开发人员来说不匹配的malloc和free容易造成内存泄露;其次频繁调用会造成大量内存碎片无法回收重新利用,降低内存利用率;最后作为系统调用,其系统开销远远大于一般函数调用。所以,为了提高内存的管理效率,高效的内存管理方案都不会直接使用malloc/free调用。Redis和Memcached均使用了自身设计的内存管理机制,但是实现方法存在很大的差异,下面将会对两者的内存管理机制分别进行介绍。

Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。Slab Allocation机制只为存储外部数据而设计,也就是说所有的key-value数据都存储在Slab Allocation系统里,而Memcached的其它内存请求则通过普通的malloc/free来申请,因为这些请求的数量和频率决定了它们不会对整个系统的性能造成影响Slab Allocation的原理相当简单。 如图所示,它首先从操作系统申请一大块内存,并将其分割成各种尺寸的块Chunk,并把尺寸相同的块分成组Slab Class。其中,Chunk就是用来存储key-value数据的最小单位。每个Slab Class的大小,可以在Memcached启动的时候通过制定Growth Factor来控制。假定图中Growth Factor的取值为1.25,如果第一组Chunk的大小为88个字节,第二组Chunk的大小就为112个字节,依此类推。

《Redis 和 Memcached 的区别》

当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的Slab Class,然后通过查询Memcached保存着的该Slab Class内空闲Chunk的列表就可以找到一个可用于存储数据的Chunk。当一条数据库过期或者丢弃时,该记录所占用的Chunk就可以回收,重新添加到空闲列表中。从以上过程我们可以看出Memcached的内存管理制效率高,而且不会造成内存碎片,但是它最大的缺点就是会导致空间浪费。因为每个Chunk都分配了特定长度的内存空间,所以变长数据无法充分利用这些空间。如图 所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了。

《Redis 和 Memcached 的区别》

Redis的内存管理主要通过源码中zmalloc.h和zmalloc.c两个文件来实现的。Redis为了方便内存的管理,在分配一块内存之后,会将这块内存的大小存入内存块的头部。如图所示,real_ptr是redis调用malloc后返回的指针。redis将内存块的大小size存入头部,size所占据的内存大小是已知的,为size_t类型的长度,然后返回ret_ptr。当需要释放内存的时候,ret_ptr被传给内存管理程序。通过ret_ptr,程序可以很容易的算出real_ptr的值,然后将real_ptr传给free释放内存。

《Redis 和 Memcached 的区别》

Redis通过定义一个数组来记录所有的内存分配情况,这个数组的长度为ZMALLOC_MAX_ALLOC_STAT。数组的每一个元素代表当前程序所分配的内存块的个数,且内存块的大小为该元素的下标。在源码中,这个数组为zmalloc_allocations。zmalloc_allocations[16]代表已经分配的长度为16bytes的内存块的个数。zmalloc.c中有一个静态变量used_memory用来记录当前分配的内存总大小。所以,总的来看,Redis采用的是包装的mallc/free,相较于Memcached的内存管理方法来说,要简单很多。

在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个操作,直到子线程完成swap操作后才可以进行修改。当从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。

Memcached使用预分配的内存池的方式,使用slab和大小不同的chunk来管理内存,Item根据大小选择合适的chunk存储,内存池的方式可以省去申请/释放内存的开销,并且能减小内存碎片产生,但这种方式也会带来一定程度上的空间浪费,并且在内存仍然有很大空间时,新的数据也可能会被剔除,原因可以参考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/

Redis使用现场申请内存的方式来存储数据,并且很少使用free-list等方式来优化内存分配,会在一定程度上存在内存碎片,Redis跟据存储命令参数,会把带过期时间的数据单独存放在一起,并把它们称为临时数据,非临时数据是永远不会被剔除的,即便物理内存不够,导致swap也不会剔除任何非临时数据(但会尝试剔除部分临时数据),这点上Redis更适合作为存储而不是cache。

数据存储及持久化

memcached不支持内存数据的持久化操作,所有的数据都以in-memory的形式存储。
redis支持持久化操作。redis提供了两种不同的持久化方法来讲数据存储到硬盘里面,一种是快照(snapshotting),它可以将存在于某一时刻的所有数据都写入硬盘里面。另一种方法叫只追加文件(append-only file, AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面。

数据一致性问题

Memcached提供了cas命令,可以保证多个并发访问操作同一份数据的一致性问题。 Redis没有提供cas 命令,并不能保证这点,不过Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断。

集群管理不同

Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。

Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。下图给出了Memcached的分布式存储实现架构。当客户端向Memcached集群发送数据之前,首先会通过内置的分布式算法计算出该条数据的目标节点,然后数据会直接发送到该节点上存储。但客户端查询数据时,同样要计算出查询数据所在的节点,然后直接向该节点发送查询请求以获取数据。

相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。最新版本的Redis已经支持了分布式存储功能。Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,具有线性可伸缩的功能。Redis Cluster的分布式存储架构,节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis Cluster将整个key的数值域分成4096个哈希槽,每个节点上可以存储一个或多个哈希槽,也就是说当前Redis Cluster支持的最大节点数就是4096。Redis Cluster使用的分布式算法也很简单:crc16( key ) % HASH_SLOTS_NUMBER。

为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。在Redis Cluster中,每个Master节点都会有对应的两个用于冗余的Slave节点。这样在整个集群中,任意两个节点的宕机都不会导致数据的不可用。当Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。

]]>
https://zuk.pw/index.php/2018/02/118.html/feed 2
MySQL 一千个不用 Null 的理由 https://zuk.pw/index.php/2018/02/109.html https://zuk.pw/index.php/2018/02/109.html#respond Sat, 03 Feb 2018 16:56:39 +0000 https://zuk.pw/?p=109 港真,Null 貌似在哪里都是个头疼的问题,比如 Java 里让人头疼的 NullPointerException,为了避免猝不及防的空指针异常,千百年来程序猿们不得不在代码里小心翼翼的各种 if 判断,麻烦而又臃肿,为此 java8 引入了 Optional 来避免这一问题。

下面咱们要聊的是 MySQL 里的 null,在大量的 MySQL 优化文章和书籍里都提到了字段尽可能用NOT NULL,而不是NULL,除非特殊情况。但却都只给结论不说明原因,犹如鸡汤不给勺子一样,让不少初学者对这个结论半信半疑或者云里雾里。本文今天就详细的剖析下使用 Null 的原因,并给出一些不用 Null 的理由。

1、NULL 为什么这么多人用?

  • NULL是创建数据表时默认的,初级或不知情的或怕麻烦的程序员不会注意这点。
  • 很多人员都以为not null 需要更多空间,其实这不是重点。
  • 重点是很多程序员觉得NULL在开发中不用去判断插入数据,写sql语句的时候更方便快捷。

2、是不是以讹传讹?

MySQL 官网文档:

NULL columns require additional space in the rowto record whether their values are NULL. For MyISAM tables, each NULL columntakes one bit extra, rounded up to the nearest byte.

Mysql难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列需要更多的存储空间,还需要mysql内部进行特殊处理。可空列被索引后,每条记录都需要一个额外的字节,还能导致MYisam 中固定大小的索引变成可变大小的索引。

—— 出自《高性能mysql第二版》

照此分析,还真不是以讹传讹,这是有理论依据和出处的。

3、给我一个不用 Null 的理由?

  • (1)所有使用NULL值的情况,都可以通过一个有意义的值的表示,这样有利于代码的可读性和可维护性,并能从约束上增强业务数据的规范性。
  • (2)NULL值到非NULL的更新无法做到原地更新,更容易发生索引分裂,从而影响性能。

注意:但把NULL列改为NOT NULL带来的性能提示很小,除非确定它带来了问题,否则不要把它当成优先的优化措施,最重要的是使用的列的类型的适当性。

  • (3)NULL值在timestamp类型下容易出问题,特别是没有启用参数explicit_defaults_for_timestamp
  • (4)NOT IN、!= 等负向条件查询在有 NULL 值的情况下返回永远为空结果,查询容易出错

《MySQL 一千个不用 Null 的理由》

create table table_2 (
     `id` INT (11) NOT NULL,
    user_name varchar(20) NOT NULL
)


create table table_3 (
     `id` INT (11) NOT NULL,
    user_name varchar(20)
)

insert into table_2 values (4,"zhaoliu_2_1"),(2,"lisi_2_1"),(3,"wangmazi_2_1"),(1,"zhangsan_2"),(2,"lisi_2_2"),(4,"zhaoliu_2_2"),(3,"wangmazi_2_2")

insert into table_3 values (1,"zhaoliu_2_1"),(2, null)

-- 1、NOT IN子查询在有NULL值的情况下返回永远为空结果,查询容易出错
select user_name from table_2 where user_name not in (select user_name from table_3 where id!=1)

mysql root@10.48.186.32:t_test_zz5431> select user_name from table_2 where user_name not
                                    -> in (select user_name from table_3 where id!=1);
+-------------+
| user_name   |
|-------------|
+-------------+
0 rows in set
Time: 0.008s
mysql root@10.48.186.32:t_test_zz5431>

-- 2、单列索引不存null值,复合索引不存全为null的值,如果列允许为null,可能会得到“不符合预期”的结果集
-- 如果name允许为null,索引不存储null值,结果集中不会包含这些记录。所以,请使用not null约束以及默认值。
select * from table_3 where name != 'zhaoliu_2_1'

-- 3、如果在两个字段进行拼接:比如题号+分数,首先要各字段进行非null判断,否则只要任意一个字段为空都会造成拼接的结果为null。
select CONCAT("1",null) from dual; -- 执行结果为null。

-- 4、如果有 Null column 存在的情况下,count(Null column)需要格外注意,null 值不会参与统计。
mysql root@10.48.186.32:t_test_zz5431> select * from table_3;
+------+-------------+
|   id | user_name   |
|------+-------------|
|    1 | zhaoliu_2_1 |
|    2 | <null>      |
|   21 | zhaoliu_2_1 |
|   22 | <null>      |
+------+-------------+
4 rows in set
Time: 0.007s
mysql root@10.48.186.32:t_test_zz5431> select count(user_name) from table_3;
+--------------------+
|   count(user_name) |
|--------------------|
|                  2 |
+--------------------+
1 row in set
Time: 0.007s

-- 5、注意 Null 字段的判断方式, = null 将会得到错误的结果。
mysql root@localhost:cygwin> create index IDX_test on table_3 (user_name);
Query OK, 0 rows affected
Time: 0.040s
mysql root@localhost:cygwin>  select * from table_3 where user_name is null\G
***************************[ 1. row ]***************************
id        | 2
user_name | None

1 row in set
Time: 0.002s
mysql root@localhost:cygwin> select * from table_3 where user_name = null\G

0 rows in set
Time: 0.002s
mysql root@localhost:cygwin> desc select * from table_3 where user_name = 'zhaoliu_2_1'\G
***************************[ 1. row ]***************************
id            | 1
select_type   | SIMPLE
table         | table_3
type          | ref
possible_keys | IDX_test
key           | IDX_test
key_len       | 23
ref           | const
rows          | 1
Extra         | Using where

1 row in set
Time: 0.006s
mysql root@localhost:cygwin> desc select * from table_3 where user_name = null\G
***************************[ 1. row ]***************************
id            | 1
select_type   | SIMPLE
table         | None
type          | None
possible_keys | None
key           | None
key_len       | None
ref           | None
rows          | None
Extra         | Impossible WHERE noticed after reading const tables

1 row in set
Time: 0.002s
mysql root@localhost:cygwin> desc select * from table_3 where user_name is null\G
***************************[ 1. row ]***************************
id            | 1
select_type   | SIMPLE
table         | table_3
type          | ref
possible_keys | IDX_test
key           | IDX_test
key_len       | 23
ref           | const
rows          | 1
Extra         | Using where

1 row in set
Time: 0.002s
mysql root@localhost:cygwin>
  • (5)Null 列需要更多的存储空间:需要一个额外字节作为判断是否为 NULL 的标志位

《MySQL 一千个不用 Null 的理由》

alter table table_3 add index idx_user_name (user_name);
alter table table_2 add index idx_user_name (user_name);
explain select * from table_2 where user_name='zhaoliu_2_1';
explain select * from table_3 where user_name='zhaoliu_2_1';

《MySQL 一千个不用 Null 的理由》

可以看到同样的 varchar(20) 长度,table_2 要比 table_3 索引长度大,这是因为:

两张表的字符集不一样,且字段一个为 NULL 一个非 NULL。

《MySQL 一千个不用 Null 的理由》

key_len 的计算规则和三个因素有关:数据类型、字符编码、是否为 NULL

key_len 62 == 20*3(utf8 3字节) + 2 (存储 varchar 变长字符长度 2字节,定长字段无需额外的字节)

key_len 83 == 20*4(utf8mb4 4字节) + 1 (是否为 Null 的标识) + 2 (存储 varchar 变长字符长度 2字节,定长字段无需额外的字节)

所以说索引字段最好不要为NULL,因为NULL会使索引、索引统计和值更加复杂,并且需要额外一个字节的存储空间。基于以上这些理由和原因,我想咱们不用 Null 的理由应该是够了 🙂

]]>
https://zuk.pw/index.php/2018/02/109.html/feed 0
编程语言简史:有人不喜欢花括号,于是他发明了 Python https://zuk.pw/index.php/2018/01/98.html https://zuk.pw/index.php/2018/01/98.html#respond Tue, 23 Jan 2018 09:47:49 +0000 https://zuk.pw/?p=98 《编程语言简史:有人不喜欢花括号,于是他发明了 Python》

编者按:编程语言有上千种,但是流行的不过10来种,那些我们经常使用的编程语言都是谁在什么时候创造出来的呢?Casper Beyer为我们进行了整理

1800年

Joseph Marie Jacquard教会了一台织布机读穿孔卡片,制造出了第一个高度多线程的处理单元。他的发明受到了预见天网(Skynet)诞生的纺织工人的强烈反对。

1842年

Ada Lovelace(英国诗人拜伦之女)对随后被认定是发布的第一个计算机程序的笔记本高贵和潦草感到厌烦,因为稍微有点不便的是当时还没有计算机呢。

1936年

阿兰·图灵发明了一切,但英国法庭却并不认可,还判处对他进行化学阉割。

女皇后来宽恕了他,但不幸的是当时他已经过世很久了。

1936年

Alonzo Church(算法理论重要奠基人)跟图灵一样也发明了一切,但他是对岸那边的,并没有被阉割。

1957年

John Backus创建了FORTRAN语言,这是真正的程序员使用的第一种语言。

1959年

Grace Hopper发明了第一门针对企业面向商业的编程语言,并且把这门语言叫做“面向商业的通用语言(common business-oriented language)”,简称COBOL。

1964年

John Kemeny 和 Thomas Kurtz 认为编程太难了,需要回归本源,他们把自己的编程语言叫做BASIC。

1970年

Niklaus Wirth开发了多种语言,最后流行起来的是PASCAL。他喜欢开发语言。

他还发明了让摩尔定律变得过时的Wirth定律(软件变慢的速度比硬件变快的速度更快),因为软件开发者会编写出连大型主机也没法跟上的臃肿软件。这在后来被证明是正确的——在Electron.js被发明出来后。

1972年

Dennis Ritchie在贝尔实验室上班上到无聊了,于是他决定写出带有花括号的C语言,这门语言取得了巨大成功。随后他又增加了分段错误等对开发者友好的功能来辅助提高生产率。

折腾完这门语言之后他还有时间,于是他跟在贝尔实验室的伙计决定给C语言做个演示程序,结果他们弄出了一个操作系统,UNIX。

1980年

Alan Kay发明了一门面向对象语言,他把这门语言叫做Smalltalk,在Smalltalk中一切都是对象,甚至一个对象也是对象。没人真正搞得清楚small talk是什么意思。

1987年

Larry Wall有宗教经验,他成为了一名牧师,并且把Perl变成了一种教义。

1983年

Jean Ichbiah注意到Ada Lovelace的程序从来都没有实际运行过,决定以她的名字开发一门语言,但是这门语言还是没有跑起来。

1986年

Brac Box 和 Tol Move决定在Smalltalk的基础上制作一个C语言的不可读版本,他们把这门语言叫做Objective-C,但是没人弄得清楚它的语法。

1983年

Bjarne Stroustrup回到未来,注意到C在编译方面花的时间还不够多,于是他把自己能想到的每一项功能都增加了进去,然后称之为C++。

每一个地方的程序员都接受了它,因为这样他们在工作的时候找借口看阿猫阿狗视频和xkcd漫画就显得比较有诚意了。

1991年

Guido van Rossum不喜欢花括号,于是他发明了Python,语法选择的灵感来源自Monty Python(巨蟒剧团)和Flying Circus(飞行马戏团)。

1993年

Roberto Ierusalimschy和他的朋友认为自己需要一个巴西本地化的脚本语言,在本地化期间发生了一个错误,这个错误会把指针从1而不是0开始计算,他们把这门语言叫做Lua。

1994年

Rasmus Lerdorf给他个人主页的CGI脚本做了一个模板引擎,后来他把自己的资料都放到了网上。

世界决定将这些东西用到一切,Rasmus于是匆忙地将一些数据库绑定做了进去,并把这门语言叫做PHP。

1995年

Yukihiro Matsumoto不是很高兴,因为他注意到其他程序员不是很高兴。他创建了Ruby来让程序员高兴。在他创建了Ruby后“Matz”高兴了,Ruby社区高兴了,每个人都高兴了。

1995年

Brendan Eich利用周末时间设计了一门语言,打算用这门语言来为全世界的每一个主流浏览器乃至于最终的Skynet都提供动力。他先是找到了Netscape然后说这门语言叫做LiveScript,但在代码评审期间Java变得流行起来,所以他们决定最好还是用花括号,然后就把它更名为JavaScript。

结果表明,Java却是一个会让他们惹上麻烦的商标,JavaScript随后更名为ECMAScript,但大家还是把它叫做JavaScript。

1996年

James Gosling发明了Java,第一们真正过于繁琐的面向对象语言,在这里设计模式完全压倒了实用主义。

于是就诞生了超级有效的管理器提供商、容器提供商、服务提供商、单一管理器提供商模式。

2001年

Anders Hejlsberg重新发明了Java然后把它叫做C#,因为用C来编程感觉要比Java酷。每个人都喜欢这个新版本的Java,因为它完全不像Java。

2005年

David Hanselmeyer Hansen创建了一个web框架叫做Ruby on Rails,从此大家不再记得Ruby和Rails是两个独立的东西了。

2006年

John Resig为JavaScript写了一个帮助库,每个人都以为那是一门语言,从此从互联网上拷贝粘贴jQuery代码就成为了一门职业。

2009年

Ken Thompson 和 Rob Pike 决定做一门类似C那样的语言,但要有更安全的装置,还要有更好的卖相,并且把Gopher(囊鼠)作为吉祥物。

他们把这门语言成为Go,并把它做成开源然后另外卖Gopher商标的护膝和头盔作为收入来源。

2010年

Graydon Hoare也想把语言做成C那样,他称之为Rust。每个人都要求马上用Rust把软件的每一块都重写一遍。Graydon希望做点更有亮点的事情,于是开始为苹果开发Swift。

2012年

Anders Hjelsberg希望在web浏览器里面写C#,于是他设计出TypeScript,这东西其实是JavaScript,但里面有了更多的Java的东西。

2013年

Jeremy Ashkenas想要像Ruby开发者一样快乐,于是他创建了CoffeeScript,这东西编译后像JavaScript但是样子又更像Ruby。Jerry从来都没有变得像Matz和Ruby开发者那样真正快乐。

2014年

Chris Lattner做Swift的时候,其主要的设计目标就是不要成为Objective-C,最后它看起来像Java。

本文最初发表在36氪,文章内容属作者个人观点,不代表本站立场。

]]>
https://zuk.pw/index.php/2018/01/98.html/feed 0
谷歌开源项目风格指南之 Python 风格指南 https://zuk.pw/index.php/2018/01/85.html https://zuk.pw/index.php/2018/01/85.html#respond Sun, 21 Jan 2018 02:50:01 +0000 https://zuk.pw/?p=85 《谷歌开源项目风格指南之 Python 风格指南》

Python 是 Google主要的脚本语言。这本风格指南主要包含的是针对python的编程准则。

为帮助读者能够将代码准确格式化,我们提供了针对 Vim的配置文件 。对于Emacs用户,保持默认设置即可。

Lint

Tip

对你的代码运行pylint

  • 定义:

    pylint是一个在Python源代码中查找bug的工具. 对于C和C++这样的不那么动态的(译者注: 原文是less dynamic)语言, 这些bug通常由编译器来捕获. 由于Python的动态特性, 有些警告可能不对. 不过伪告警应该很少.

  • 优点:

    可以捕获容易忽视的错误, 例如输入错误, 使用未赋值的变量等.

  • 缺点:

    pylint不完美. 要利用其优势, 我们有时侯需要: a) 围绕着它来写代码 b) 抑制其告警 c) 改进它, 或者d) 忽略它.

  • 结论:

    确保对你的代码运行pylint.抑制不准确的警告,以便能够将其他警告暴露出来。你可以通过设置一个行注释来抑制告警. 例如:dict = 'something awful' # Bad Idea... pylint: disable=redefined-builtinpylint警告是以一个数字编号(如 C0112 )和一个符号名(如 empty-docstring )来标识的. 在编写新代码或更新已有代码时对告警进行抑制, 推荐使用符号名来标识.如果警告的符号名不够见名知意,那么请对其增加一个详细解释。采用这种抑制方式的好处是我们可以轻松查找抑制并回顾它们.你可以使用命令 pylint --list-msgs 来获取pylint告警列表. 你可以使用命令 pylint --help-msg=C6409 , 以获取关于特定消息的更多信息.相比较于之前使用的 pylint: disable-msg , 本文推荐使用 pylint: disable .要抑制”参数未使用”告警, 你可以用””作为参数标识符, 或者在参数名前加”unused”. 遇到不能改变参数名的情况, 你可以通过在函数开头”提到”它们来消除告警. 例如:def foo(a, unused_b, unused_c, d=None, e=None): _ = d, e return a

导入

Tip

仅对包和模块使用导入

  • 定义:

    模块间共享代码的重用机制.

  • 优点:

    命名空间管理约定十分简单. 每个标识符的源都用一种一致的方式指示. x.Obj表示Obj对象定义在模块x中.

  • 缺点:

    模块名仍可能冲突. 有些模块名太长, 不太方便.

  • 结论:

    使用 import x 来导入包和模块.使用 from x import y , 其中x是包前缀, y是不带前缀的模块名.使用 from x import y as z, 如果两个要导入的模块都叫做y或者y太长了.例如, 模块 sound.effects.echo 可以用如下方式导入:from sound.effects import echo...echo.EchoFilter(input, output, delay=0.7, atten=4)导入时不要使用相对名称. 即使模块在同一个包中, 也要使用完整包名. 这能帮助你避免无意间导入一个包两次.

Tip

使用模块的全路径名来导入每个模块

  • 优点:

    避免模块名冲突. 查找包更容易.

  • 缺点:

    部署代码变难, 因为你必须复制包层次.

  • 结论:

    所有的新代码都应该用完整包名来导入每个模块.应该像下面这样导入:# Reference in code with complete name.import sound.effects.echo# Reference in code with just module name (preferred).from sound.effects import echo

异常

Tip

允许使用异常, 但必须小心

  • 定义:

    异常是一种跳出代码块的正常控制流来处理错误或者其它异常条件的方式.

  • 优点:

    正常操作代码的控制流不会和错误处理代码混在一起. 当某种条件发生时, 它也允许控制流跳过多个框架. 例如, 一步跳出N个嵌套的函数, 而不必继续执行错误的代码.

  • 缺点:

    可能会导致让人困惑的控制流. 调用库时容易错过错误情况.

  • 结论:

    异常必须遵守特定条件:像这样触发异常: raise MyException("Error message") 或者 raise MyException . 不要使用两个参数的形式( raise MyException, "Error message" )或者过时的字符串异常( raise "Error message" ).模块或包应该定义自己的特定域的异常基类, 这个基类应该从内建的Exception类继承. 模块的异常基类应该叫做”Error”.class Error(Exception): pass永远不要使用 except: 语句来捕获所有异常, 也不要捕获 Exception 或者 StandardError , 除非你打算重新触发该异常, 或者你已经在当前线程的最外层(记得还是要打印一条错误消息). 在异常这方面, Python非常宽容, except: 真的会捕获包括Python语法错误在内的任何错误. 使用 except: 很容易隐藏真正的bug.尽量减少try/except块中的代码量. try块的体积越大, 期望之外的异常就越容易被触发. 这种情况下, try/except块将隐藏真正的错误.使用finally子句来执行那些无论try块中有没有异常都应该被执行的代码. 这对于清理资源常常很有用, 例如关闭文件.当捕获异常时, 使用 as 而不要用逗号. 例如try: raise Errorexcept Error as error: pass

全局变量

Tip

避免全局变量

  • 定义:

    定义在模块级的变量.

  • 优点:

    偶尔有用.

  • 缺点:

    导入时可能改变模块行为, 因为导入模块时会对模块级变量赋值.

  • 结论:

    避免使用全局变量, 用类变量来代替. 但也有一些例外:脚本的默认选项.模块级常量. 例如: PI = 3.14159. 常量应该全大写, 用下划线连接.有时候用全局变量来缓存值或者作为函数返回值很有用.如果需要, 全局变量应该仅在模块内部可用, 并通过模块级的公共函数来访问.

嵌套/局部/内部类或函数

Tip

鼓励使用嵌套/本地/内部类或函数

  • 定义:

    类可以定义在方法, 函数或者类中. 函数可以定义在方法或函数中. 封闭区间中定义的变量对嵌套函数是只读的.

  • 优点:

    允许定义仅用于有效范围的工具类和函数.

  • 缺点:

    嵌套类或局部类的实例不能序列化(pickled).

  • 结论:

    推荐使用.

列表推导(List Comprehensions)

Tip

可以在简单情况下使用

  • 定义:

    列表推导(list comprehensions)与生成器表达式(generator expression)提供了一种简洁高效的方式来创建列表和迭代器, 而不必借助map(), filter(), 或者lambda.

  • 优点:

    简单的列表推导可以比其它的列表创建方法更加清晰简单. 生成器表达式可以十分高效, 因为它们避免了创建整个列表.

  • 缺点:

    复杂的列表推导或者生成器表达式可能难以阅读.

  • 结论:

    适用于简单情况. 每个部分应该单独置于一行: 映射表达式, for语句, 过滤器表达式. 禁止多重for语句或过滤器表达式. 复杂情况下还是使用循环.Yes: result = [] for x in range(10): for y in range(5): if x * y > 10: result.append((x, y)) for x in xrange(5): for y in xrange(5): if x != y: for z in xrange(5): if y != z: yield (x, y, z) return ((x, complicated_transform(x)) for x in long_generator_function(parameter) if x is not None) squares = [x * x for x in range(10)] eat(jelly_bean for jelly_bean in jelly_beans if jelly_bean.color == 'black')``No: result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] return ((x, y, z) for x in xrange(5) for y in xrange(5) if x != y for z in xrange(5) if y != z)

默认迭代器和操作符

Tip

如果类型支持, 就使用默认迭代器和操作符. 比如列表, 字典及文件等.

  • 定义:

    容器类型, 像字典和列表, 定义了默认的迭代器和关系测试操作符(in和not in)

  • 优点:

    默认操作符和迭代器简单高效, 它们直接表达了操作, 没有额外的方法调用. 使用默认操作符的函数是通用的. 它可以用于支持该操作的任何类型.

  • 缺点:

    你没法通过阅读方法名来区分对象的类型(例如, has_key()意味着字典). 不过这也是优点.

  • 结论:

    如果类型支持, 就使用默认迭代器和操作符, 例如列表, 字典和文件. 内建类型也定义了迭代器方法. 优先考虑这些方法, 而不是那些返回列表的方法. 当然,这样遍历容器时,你将不能修改容器.Yes: for key in adict: ... if key not in adict: ... if obj in alist: ... for line in afile: ... for k, v in dict.iteritems(): ...``No: for key in adict.keys(): ... if not adict.has_key(key): ... for line in afile.readlines(): ...

生成器

Tip

按需使用生成器.

  • 定义:

    所谓生成器函数, 就是每当它执行一次生成(yield)语句, 它就返回一个迭代器, 这个迭代器生成一个值. 生成值后, 生成器函数的运行状态将被挂起, 直到下一次生成.

  • 优点:

    简化代码, 因为每次调用时, 局部变量和控制流的状态都会被保存. 比起一次创建一系列值的函数, 生成器使用的内存更少.

  • 缺点:

    没有.

  • 结论:

    鼓励使用. 注意在生成器函数的文档字符串中使用”Yields:”而不是”Returns:”.(译者注: 参看 注释 )

Lambda函数

Tip

适用于单行函数

  • 定义:

    与语句相反, lambda在一个表达式中定义匿名函数. 常用于为 map()filter() 之类的高阶函数定义回调函数或者操作符.

  • 优点:

    方便.

  • 缺点:

    比本地函数更难阅读和调试. 没有函数名意味着堆栈跟踪更难理解. 由于lambda函数通常只包含一个表达式, 因此其表达能力有限.

  • 结论:

    适用于单行函数. 如果代码超过60-80个字符, 最好还是定义成常规(嵌套)函数.对于常见的操作符,例如乘法操作符,使用 operator 模块中的函数以代替lambda函数. 例如, 推荐使用 operator.mul , 而不是 lambda x, y: x * y .

条件表达式

Tip

适用于单行函数

  • 定义:

    条件表达式是对于if语句的一种更为简短的句法规则. 例如: x = 1 if cond else 2 .

  • 优点:

    比if语句更加简短和方便.

  • 缺点:

    比if语句难于阅读. 如果表达式很长, 难于定位条件.

  • 结论:

    适用于单行函数. 在其他情况下,推荐使用完整的if语句.

默认参数值

Tip

适用于大部分情况.

  • 定义:

    你可以在函数参数列表的最后指定变量的值, 例如, def foo(a, b = 0): . 如果调用foo时只带一个参数, 则b被设为0. 如果带两个参数, 则b的值等于第二个参数.

  • 优点:

    你经常会碰到一些使用大量默认值的函数, 但偶尔(比较少见)你想要覆盖这些默认值. 默认参数值提供了一种简单的方法来完成这件事, 你不需要为这些罕见的例外定义大量函数. 同时, Python也不支持重载方法和函数, 默认参数是一种”仿造”重载行为的简单方式.

  • 缺点:

    默认参数只在模块加载时求值一次. 如果参数是列表或字典之类的可变类型, 这可能会导致问题. 如果函数修改了对象(例如向列表追加项), 默认值就被修改了.

  • 结论:

    鼓励使用, 不过有如下注意事项:不要在函数或方法定义中使用可变对象作为默认值.Yes: def foo(a, b=None): if b is None: b = []``No: def foo(a, b=[]): ...No: def foo(a, b=time.time()): # The time the module was loaded??? ...No: def foo(a, b=FLAGS.my_thing): # sys.argv has not yet been parsed... ...

属性(properties)

Tip

访问和设置数据成员时, 你通常会使用简单, 轻量级的访问和设置函数. 建议用属性(properties)来代替它们.

  • 定义:

    一种用于包装方法调用的方式. 当运算量不大, 它是获取和设置属性(attribute)的标准方式.

  • 优点:

    通过消除简单的属性(attribute)访问时显式的get和set方法调用, 可读性提高了. 允许懒惰的计算. 用Pythonic的方式来维护类的接口. 就性能而言, 当直接访问变量是合理的, 添加访问方法就显得琐碎而无意义. 使用属性(properties)可以绕过这个问题. 将来也可以在不破坏接口的情况下将访问方法加上.

  • 缺点:

    属性(properties)是在get和set方法声明后指定, 这需要使用者在接下来的代码中注意: set和get是用于属性(properties)的(除了用 @property 装饰器创建的只读属性). 必须继承自object类. 可能隐藏比如操作符重载之类的副作用. 继承时可能会让人困惑.

  • 结论:

    你通常习惯于使用访问或设置方法来访问或设置数据, 它们简单而轻量. 不过我们建议你在新的代码中使用属性. 只读属性应该用 @property 装饰器 来创建.如果子类没有覆盖属性, 那么属性的继承可能看上去不明显. 因此使用者必须确保访问方法间接被调用, 以保证子类中的重载方法被属性调用(使用模板方法设计模式).Yes: import math class Square(object): """A square with two properties: a writable area and a read-only perimeter. To use: >>> sq = Square(3) >>> sq.area 9 >>> sq.perimeter 12 >>> sq.area = 16 >>> sq.side 4 >>> sq.perimeter 16 """ def __init__(self, side): self.side = side def __get_area(self): """Calculates the 'area' property.""" return self.side ** 2 def ___get_area(self): """Indirect accessor for 'area' property.""" return self.__get_area() def __set_area(self, area): """Sets the 'area' property.""" self.side = math.sqrt(area) def ___set_area(self, area): """Indirect setter for 'area' property.""" self._SetArea(area) area = property(___get_area, ___set_area, doc="""Gets or sets the area of the square.""") @property def perimeter(self): return self.side * 4(译者注: 老实说, 我觉得这段示例代码很不恰当, 有必要这么蛋疼吗?)

True/False的求值

Tip

尽可能使用隐式false

  • 定义:

    Python在布尔上下文中会将某些值求值为false. 按简单的直觉来讲, 就是所有的”空”值都被认为是false. 因此0, None, [], {}, “” 都被认为是false.

  • 优点:

    使用Python布尔值的条件语句更易读也更不易犯错. 大部分情况下, 也更快.

  • 缺点:

    对C/C++开发人员来说, 可能看起来有点怪.

  • 结论:

    尽可能使用隐式的false, 例如: 使用 if foo: 而不是 if foo != []: . 不过还是有一些注意事项需要你铭记在心:永远不要用==或者!=来比较单件, 比如None. 使用is或者is not.注意: 当你写下 if x: 时, 你其实表示的是 if x is not None . 例如: 当你要测试一个默认值是None的变量或参数是否被设为其它值. 这个值在布尔语义下可能是false!永远不要用==将一个布尔量与false相比较. 使用 if not x: 代替. 如果你需要区分false和None, 你应该用像 if not x and x is not None: 这样的语句.对于序列(字符串, 列表, 元组), 要注意空序列是false. 因此 if not seq: 或者 if seq:if len(seq):if not len(seq): 要更好.处理整数时, 使用隐式false可能会得不偿失(即不小心将None当做0来处理). 你可以将一个已知是整型(且不是len()的返回结果)的值与0比较.Yes: if not users: print 'no users' if foo == 0: self.handle_zero() if i % 10 == 0: self.handle_multiple_of_ten()``No: if len(users) == 0: print 'no users' if foo is not None and not foo: self.handle_zero() if not i % 10: self.handle_multiple_of_ten()注意‘0’(字符串)会被当做true.

过时的语言特性

Tip

尽可能使用字符串方法取代字符串模块. 使用函数调用语法取代apply(). 使用列表推导, for循环取代filter(), map()以及reduce().

  • 定义:

    当前版本的Python提供了大家通常更喜欢的替代品.

  • 结论:

    我们不使用不支持这些特性的Python版本, 所以没理由不用新的方式.Yes: words = foo.split(':') [x[1] for x in my_list if x[2] == 5] map(math.sqrt, data) # Ok. No inlined lambda expression. fn(*args, **kwargs)``No: words = string.split(foo, ':') map(lambda x: x[1], filter(lambda x: x[2] == 5, my_list)) apply(fn, args, kwargs)

词法作用域(Lexical Scoping)

Tip

推荐使用

  • 定义:

    嵌套的Python函数可以引用外层函数中定义的变量, 但是不能够对它们赋值. 变量绑定的解析是使用词法作用域, 也就是基于静态的程序文本. 对一个块中的某个名称的任何赋值都会导致Python将对该名称的全部引用当做局部变量, 甚至是赋值前的处理. 如果碰到global声明, 该名称就会被视作全局变量.一个使用这个特性的例子:def get_adder(summand1): """Returns a function that adds numbers to a given number.""" def adder(summand2): return summand1 + summand2 return adder(译者注: 这个例子有点诡异, 你应该这样使用这个函数: sum = get_adder(summand1)(summand2) )

  • 优点:

    通常可以带来更加清晰, 优雅的代码. 尤其会让有经验的Lisp和Scheme(还有Haskell, ML等)程序员感到欣慰.

  • 缺点:

    可能导致让人迷惑的bug. 例如下面这个依据 PEP-0227 的例子:i = 4def foo(x): def bar(): print i, # ... # A bunch of code here # ... for i in x: # Ah, i *is* local to Foo, so this is what Bar sees print i, bar()因此 foo([1, 2, 3]) 会打印 1 2 3 3 , 不是 1 2 3 4 .(译者注: x是一个列表, for循环其实是将x中的值依次赋给i.这样对i的赋值就隐式的发生了, 整个foo函数体中的i都会被当做局部变量, 包括bar()中的那个. 这一点与C++之类的静态语言还是有很大差别的.)

  • 结论:

    鼓励使用.

函数与方法装饰器

Tip

如果好处很显然, 就明智而谨慎的使用装饰器

  • 定义:

    用于函数及方法的装饰器 (也就是@标记). 最常见的装饰器是@classmethod 和@staticmethod, 用于将常规函数转换成类方法或静态方法. 不过, 装饰器语法也允许用户自定义装饰器. 特别地, 对于某个函数 my_decorator , 下面的两段代码是等效的:class C(object): @my_decorator def method(self): # method body ...``class C(object): def method(self): # method body ... method = my_decorator(method)

  • 优点:

    优雅的在函数上指定一些转换. 该转换可能减少一些重复代码, 保持已有函数不变(enforce invariants), 等.

  • 缺点:

    装饰器可以在函数的参数或返回值上执行任何操作, 这可能导致让人惊异的隐藏行为. 而且, 装饰器在导入时执行. 从装饰器代码的失败中恢复更加不可能.

  • 结论:

    如果好处很显然, 就明智而谨慎的使用装饰器. 装饰器应该遵守和函数一样的导入和命名规则. 装饰器的python文档应该清晰的说明该函数是一个装饰器. 请为装饰器编写单元测试.避免装饰器自身对外界的依赖(即不要依赖于文件, socket, 数据库连接等), 因为装饰器运行时这些资源可能不可用(由 pydoc 或其它工具导入). 应该保证一个用有效参数调用的装饰器在所有情况下都是成功的.装饰器是一种特殊形式的”顶级代码”. 参考后面关于 Main 的话题.

线程

Tip

不要依赖内建类型的原子性.

虽然Python的内建类型例如字典看上去拥有原子操作, 但是在某些情形下它们仍然不是原子的(即: 如果hasheq被实现为Python方法)且它们的原子性是靠不住的. 你也不能指望原子变量赋值(因为这个反过来依赖字典).

优先使用Queue模块的 Queue 数据类型作为线程间的数据通信方式. 另外, 使用threading模块及其锁原语(locking primitives). 了解条件变量的合适使用方式, 这样你就可以使用 threading.Condition 来取代低级别的锁了.

威力过大的特性

Tip

避免使用这些特性

  • 定义:

    Python是一种异常灵活的语言, 它为你提供了很多花哨的特性, 诸如元类(metaclasses), 字节码访问, 任意编译(on-the-fly compilation), 动态继承, 对象父类重定义(object reparenting), 导入黑客(import hacks), 反射, 系统内修改(modification of system internals), 等等.

  • 优点:

    强大的语言特性, 能让你的代码更紧凑.

  • 缺点:

    使用这些很”酷”的特性十分诱人, 但不是绝对必要. 使用奇技淫巧的代码将更加难以阅读和调试. 开始可能还好(对原作者而言), 但当你回顾代码, 它们可能会比那些稍长一点但是很直接的代码更加难以理解.

  • 结论:

    在你的代码中避免这些特性.

分号

Tip

不要在行尾加分号, 也不要用分号将两条命令放在同一行.

行长度

Tip

每行不超过80个字符

例外:

  1. 长的导入模块语句
  2. 注释里的URL

不要使用反斜杠连接行.

Python会将 圆括号, 中括号和花括号中的行隐式的连接起来 , 你可以利用这个特点. 如果需要, 你可以在表达式外围增加一对额外的圆括号.

Yes: foo_bar(self, width, height, color='black', design=None, x='foo',
             emphasis=None, highlight=0)

     if (width == 0 and height == 0 and
         color == 'red' and emphasis == 'strong'):

如果一个文本字符串在一行放不下, 可以使用圆括号来实现隐式行连接:

x = ('This will build a very long long '
     'long long long long long long string')

在注释中,如果必要,将长的URL放在一行上。

Yes:  # See details at
      # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html

No:  # See details at
     # http://www.example.com/us/developer/documentation/api/content/\
     # v2.0/csv_file_name_extension_full_specification.html

注意上面例子中的元素缩进; 你可以在本文的 缩进 部分找到解释.

括号

Tip

宁缺毋滥的使用括号

除非是用于实现行连接, 否则不要在返回语句或条件语句中使用括号. 不过在元组两边使用括号是可以的.

Yes: if foo:
         bar()
     while x:
         x = bar()
     if x and y:
         bar()
     if not x:
         bar()
     return foo
     for (x, y) in dict.items(): ...

No:  if (x):
         bar()
     if not(x):
         bar()
     return (foo)

缩进

Tip

用4个空格来缩进代码

绝对不要用tab, 也不要tab和空格混用. 对于行连接的情况, 你应该要么垂直对齐换行的元素(见 行长度 部分的示例), 或者使用4空格的悬挂式缩进(这时第一行不应该有参数):

Yes:   # Aligned with opening delimiter
       foo = long_function_name(var_one, var_two,
                                var_three, var_four)

       # Aligned with opening delimiter in a dictionary
       foo = {
           long_dictionary_key: value1 +
                                value2,
           ...
       }

       # 4-space hanging indent; nothing on first line
       foo = long_function_name(
           var_one, var_two, var_three,
           var_four)

       # 4-space hanging indent in a dictionary
       foo = {
           long_dictionary_key:
               long_dictionary_value,
           ...
       }

No:    # Stuff on first line forbidden
      foo = long_function_name(var_one, var_two,
          var_three, var_four)

      # 2-space hanging indent forbidden
      foo = long_function_name(
        var_one, var_two, var_three,
        var_four)

      # No hanging indent in a dictionary
      foo = {
          long_dictionary_key:
              long_dictionary_value,
              ...
      }

空行

Tip

顶级定义之间空两行, 方法定义之间空一行

顶级定义之间空两行, 比如函数或者类定义. 方法定义, 类定义与第一个方法之间, 都应该空一行. 函数或方法中, 某些地方要是你觉得合适, 就空一行.

空格

Tip

按照标准的排版规范来使用标点两边的空格

括号内不要有空格.

Yes: spam(ham[1], {eggs: 2}, [])

No:  spam( ham[ 1 ], { eggs: 2 }, [ ] )

不要在逗号, 分号, 冒号前面加空格, 但应该在它们后面加(除了在行尾).

Yes: if x == 4:
         print x, y
     x, y = y, x

No:  if x == 4 :
         print x , y
     x , y = y , x

参数列表, 索引或切片的左括号前不应加空格.

Yes: spam(1)

no: spam (1)

Yes: dict['key'] = list[index]

No:  dict ['key'] = list [index]

在二元操作符两边都加上一个空格, 比如赋值(=), 比较(==, <, >, !=, <>, <=, >=, in, not in, is, is not), 布尔(and, or, not). 至于算术操作符两边的空格该如何使用, 需要你自己好好判断. 不过两侧务必要保持一致.

Yes: x == 1

No:  x<1

当’=’用于指示关键字参数或默认参数值时, 不要在其两侧使用空格.

Yes: def complex(real, imag=0.0): return magic(r=real, i=imag)

No:  def complex(real, imag = 0.0): return magic(r = real, i = imag)

不要用空格来垂直对齐多行间的标记, 因为这会成为维护的负担(适用于:, #, =等):

Yes:
     foo = 1000  # comment
     long_name = 2  # comment that should not be aligned

     dictionary = {
         "foo": 1,
         "long_name": 2,
         }

No:
     foo       = 1000  # comment
     long_name = 2     # comment that should not be aligned

     dictionary = {
         "foo"      : 1,
         "long_name": 2,
         }

Shebang

Tip

大部分.py文件不必以#!作为文件的开始. 根据 PEP-394 , 程序的main文件应该以 #!/usr/bin/python2或者 #!/usr/bin/python3开始.

(译者注: 在计算机科学中, Shebang (也称为Hashbang)是一个由井号和叹号构成的字符串行(#!), 其出现在文本文件的第一行的前两个字符. 在文件中存在Shebang的情况下, 类Unix操作系统的程序载入器会分析Shebang后的内容, 将这些内容作为解释器指令, 并调用该指令, 并将载有Shebang的文件路径作为该解释器的参数. 例如, 以指令#!/bin/sh开头的文件在执行时会实际调用/bin/sh程序.)

#!先用于帮助内核找到Python解释器, 但是在导入模块时, 将会被忽略. 因此只有被直接执行的文件中才有必要加入#!.

注释

Tip

确保对模块, 函数, 方法和行内注释使用正确的风格

文档字符串

Python有一种独一无二的的注释方式: 使用文档字符串. 文档字符串是包, 模块, 类或函数里的第一个语句. 这些字符串可以通过对象的doc成员被自动提取, 并且被pydoc所用. (你可以在你的模块上运行pydoc试一把, 看看它长什么样). 我们对文档字符串的惯例是使用三重双引号”“”( PEP-257 ). 一个文档字符串应该这样组织: 首先是一行以句号, 问号或惊叹号结尾的概述(或者该文档字符串单纯只有一行). 接着是一个空行. 接着是文档字符串剩下的部分, 它应该与文档字符串的第一行的第一个引号对齐. 下面有更多文档字符串的格式化规范.

模块

每个文件应该包含一个许可样板. 根据项目使用的许可(例如, Apache 2.0, BSD, LGPL, GPL), 选择合适的样板.

函数和方法

下文所指的函数,包括函数, 方法, 以及生成器.

一个函数必须要有文档字符串, 除非它满足以下条件:

  1. 外部不可见
  2. 非常短小
  3. 简单明了

文档字符串应该包含函数做什么, 以及输入和输出的详细描述. 通常, 不应该描述”怎么做”, 除非是一些复杂的算法. 文档字符串应该提供足够的信息, 当别人编写代码调用该函数时, 他不需要看一行代码, 只要看文档字符串就可以了. 对于复杂的代码, 在代码旁边加注释会比使用文档字符串更有意义.

关于函数的几个方面应该在特定的小节中进行描述记录, 这几个方面如下文所述. 每节应该以一个标题行开始. 标题行以冒号结尾. 除标题行外, 节的其他内容应被缩进2个空格.

  • Args:

    列出每个参数的名字, 并在名字后使用一个冒号和一个空格, 分隔对该参数的描述.如果描述太长超过了单行80字符,使用2或者4个空格的悬挂缩进(与文件其他部分保持一致). 描述应该包括所需的类型和含义. 如果一个函数接受*foo(可变长度参数列表)或者bar (任意关键字参数), 应该详细列出*foo和bar.

  • Returns: (或者 Yields: 用于生成器)

    描述返回值的类型和语义. 如果函数返回None, 这一部分可以省略.

  • Raises:

    列出与接口有关的所有异常.

def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
      """Fetches rows from a Bigtable.
  
      Retrieves rows pertaining to the given keys from the Table instance
      represented by big_table.  Silly things may happen if
      other_silly_variable is not None.
  
      Args:
          big_table: An open Bigtable Table instance.
          keys: A sequence of strings representing the key of each table row
              to fetch.
          other_silly_variable: Another optional variable, that has a much
              longer name than the other args, and which does nothing.
  
      Returns:
          A dict mapping keys to the corresponding table row data
          fetched. Each row is represented as a tuple of strings. For
          example:
  
          {'Serak': ('Rigel VII', 'Preparer'),
           'Zim': ('Irk', 'Invader'),
           'Lrrr': ('Omicron Persei 8', 'Emperor')}
  
          If a key from the keys argument is missing from the dictionary,
          then that row was not found in the table.
  
      Raises:
          IOError: An error occurred accessing the bigtable.Table object.
      """
      pass
  
  

类应该在其定义下有一个用于描述该类的文档字符串. 如果你的类有公共属性(Attributes), 那么文档中应该有一个属性(Attributes)段. 并且应该遵守和函数参数相同的格式.

class SampleClass(object):
      """Summary of class here.
  
      Longer class information....
      Longer class information....
  
      Attributes:
          likes_spam: A boolean indicating if we like SPAM or not.
          eggs: An integer count of the eggs we have laid.
      """
  
      def __init__(self, likes_spam=False):
          """Inits SampleClass with blah."""
          self.likes_spam = likes_spam
          self.eggs = 0
  
      def public_method(self):
          """Performs operation blah."""
  
  

块注释和行注释

最需要写注释的是代码中那些技巧性的部分. 如果你在下次 代码审查 的时候必须解释一下, 那么你应该现在就给它写注释. 对于复杂的操作, 应该在其操作开始前写上若干行注释. 对于不是一目了然的代码, 应在其行尾添加注释.

# We use a weighted dictionary search to find out where i is in
  # the array.  We extrapolate position based on the largest num
  # in the array and the array size and then do binary search to
  # get the exact number.
  
  if i & (i-1) == 0:        # true iff i is a power of 2
  
  

为了提高可读性, 注释应该至少离开代码2个空格.

另一方面, 绝不要描述代码. 假设阅读代码的人比你更懂Python, 他只是不知道你的代码要做什么.

# BAD COMMENT: Now go through the b array and make sure whenever i occurs
  # the next element is i+1
  
  

Tip

如果一个类不继承自其它类, 就显式的从object继承. 嵌套类也一样.

Yes: class SampleClass(object):
         pass


     class OuterClass(object):

         class InnerClass(object):
             pass


     class ChildClass(ParentClass):
         """Explicitly inherits from another class already."""

No: class SampleClass:
        pass


    class OuterClass:

        class InnerClass:
            pass

继承自 object 是为了使属性(properties)正常工作, 并且这样可以保护你的代码, 使其不受 PEP-3000的一个特殊的潜在不兼容性影响. 这样做也定义了一些特殊的方法, 这些方法实现了对象的默认语义, 包括 __new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__, __repr__, and __str__ .

字符串

Tip

即使参数都是字符串, 使用%操作符或者格式化方法格式化字符串. 不过也不能一概而论, 你需要在+和%之间好好判定.

Yes: x = a + b
     x = '%s, %s!' % (imperative, expletive)
     x = '{}, {}!'.format(imperative, expletive)
     x = 'name: %s; score: %d' % (name, n)
     x = 'name: {}; score: {}'.format(name, n)

No: x = '%s%s' % (a, b)  # use + in this case
    x = '{}{}'.format(a, b)  # use + in this case
    x = imperative + ', ' + expletive + '!'
    x = 'name: ' + name + '; score: ' + str(n)

避免在循环中用+和+=操作符来累加字符串. 由于字符串是不可变的, 这样做会创建不必要的临时对象, 并且导致二次方而不是线性的运行时间. 作为替代方案, 你可以将每个子串加入列表, 然后在循环结束后用 .join 连接列表. (也可以将每个子串写入一个 cStringIO.StringIO 缓存中.)

Yes: items = ['

']
     for last_name, first_name in employee_list:
         items.append('' % (last_name, first_name))
     items.append('
%s, %s
') employee_table = ''.join(items)
No: employee_table = '

'
    for last_name, first_name in employee_list:
        employee_table += '' % (last_name, first_name)
    employee_table += '
%s, %s
'

在同一个文件中, 保持使用字符串引号的一致性. 使用单引号’或者双引号”之一用以引用字符串, 并在同一文件中沿用. 在字符串内可以使用另外一种引号, 以避免在字符串中使用. GPyLint已经加入了这一检查.

(译者注:GPyLint疑为笔误, 应为PyLint.)

Yes:
     Python('Why are you hiding your eyes?')
     Gollum("I'm scared of lint errors.")
     Narrator('"Good!" thought a happy Python reviewer.')

No:
     Python("Why are you hiding your eyes?")
     Gollum('The lint. It burns. It burns us.')
     Gollum("Always the great lint. Watching. Watching.")

为多行字符串使用三重双引号”“”而非三重单引号’‘’. 当且仅当项目中使用单引号’来引用字符串时, 才可能会使用三重’‘’为非文档字符串的多行字符串来标识引用. 文档字符串必须使用三重双引号”“”. 不过要注意, 通常用隐式行连接更清晰, 因为多行字符串与程序其他部分的缩进方式不一致.

Yes:
    print ("This is much nicer.\n"
           "Do it this way.\n")

No:
      print """This is pretty ugly.
  Don't do this.
  """

文件和sockets

Tip

在文件和sockets结束时, 显式的关闭它.

除文件外, sockets或其他类似文件的对象在没有必要的情况下打开, 会有许多副作用, 例如:

  1. 它们可能会消耗有限的系统资源, 如文件描述符. 如果这些资源在使用后没有及时归还系统, 那么用于处理这些对象的代码会将资源消耗殆尽.
  2. 持有文件将会阻止对于文件的其他诸如移动、删除之类的操作.
  3. 仅仅是从逻辑上关闭文件和sockets, 那么它们仍然可能会被其共享的程序在无意中进行读或者写操作. 只有当它们真正被关闭后, 对于它们尝试进行读或者写操作将会抛出异常, 并使得问题快速显现出来.

而且, 幻想当文件对象析构时, 文件和sockets会自动关闭, 试图将文件对象的生命周期和文件的状态绑定在一起的想法, 都是不现实的. 因为有如下原因:

  1. 没有任何方法可以确保运行环境会真正的执行文件的析构. 不同的Python实现采用不同的内存管理技术, 比如延时垃圾处理机制. 延时垃圾处理机制可能会导致对象生命周期被任意无限制的延长.
  2. 对于文件意外的引用,会导致对于文件的持有时间超出预期(比如对于异常的跟踪, 包含有全局变量等).

推荐使用 “with”语句 以管理文件:

with open("hello.txt") as hello_file:
    for line in hello_file:
        print line

对于不支持使用”with”语句的类似文件的对象,使用 contextlib.closing():

import contextlib

with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page:
    for line in front_page:
        print line

Legacy AppEngine 中Python 2.5的代码如使用”with”语句, 需要添加 “from future import with_statement”.

TODO注释

Tip

为临时代码使用TODO注释, 它是一种短期解决方案. 不算完美, 但够好了.

TODO注释应该在所有开头处包含”TODO”字符串, 紧跟着是用括号括起来的你的名字, email地址或其它标识符. 然后是一个可选的冒号. 接着必须有一行注释, 解释要做什么. 主要目的是为了有一个统一的TODO格式, 这样添加注释的人就可以搜索到(并可以按需提供更多细节). 写了TODO注释并不保证写的人会亲自解决问题. 当你写了一个TODO, 请注上你的名字.

# TODO(kl@gmail.com): Use a "*" here for string repetition.
# TODO(Zeke) Change this to use relations.

如果你的TODO是”将来做某事”的形式, 那么请确保你包含了一个指定的日期(“2009年11月解决”)或者一个特定的事件(“等到所有的客户都可以处理XML请求就移除这些代码”).

导入格式

Tip

每个导入应该独占一行

Yes: import os
     import sys

No:  import os, sys

导入总应该放在文件顶部, 位于模块注释和文档字符串之后, 模块全局变量和常量之前. 导入应该按照从最通用到最不通用的顺序分组:

  1. 标准库导入
  2. 第三方库导入
  3. 应用程序指定导入

每种分组中, 应该根据每个模块的完整包路径按字典序排序, 忽略大小写.

import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar

语句

Tip

通常每个语句应该独占一行

不过, 如果测试结果与测试语句在一行放得下, 你也可以将它们放在同一行. 如果是if语句, 只有在没有else时才能这样做. 特别地, 绝不要对 try/except 这样做, 因为try和except不能放在同一行.

Yes:

  if foo: bar(foo)

No:

  if foo: bar(foo)
  else:   baz(foo)

  try:               bar(foo)
  except ValueError: baz(foo)

  try:
      bar(foo)
  except ValueError: baz(foo)

访问控制

Tip

在Python中, 对于琐碎又不太重要的访问函数, 你应该直接使用公有变量来取代它们, 这样可以避免额外的函数调用开销. 当添加更多功能时, 你可以用属性(property)来保持语法的一致性.

(译者注: 重视封装的面向对象程序员看到这个可能会很反感, 因为他们一直被教育: 所有成员变量都必须是私有的! 其实, 那真的是有点麻烦啊. 试着去接受Pythonic哲学吧)

另一方面, 如果访问更复杂, 或者变量的访问开销很显著, 那么你应该使用像 get_foo()set_foo()这样的函数调用. 如果之前的代码行为允许通过属性(property)访问 , 那么就不要将新的访问函数与属性绑定. 这样, 任何试图通过老方法访问变量的代码就没法运行, 使用者也就会意识到复杂性发生了变化.

命名

Tip

module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_VAR_NAME, instance_var_name, function_parameter_name, local_var_name.

应该避免的名称

  1. 单字符名称, 除了计数器和迭代器.
  2. 包/模块名中的连字符(-)
  3. 双下划线开头并结尾的名称(Python保留, 例如init)

命名约定

  1. 所谓”内部(Internal)”表示仅模块内可用, 或者, 在类内是保护或私有的.
  2. 用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含).
  3. 用双下划线(__)开头的实例变量或方法表示类内私有.
  4. 将相关的类和顶级函数放在同一个模块里. 不像Java, 没必要限制一个类一个模块.
  5. 对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py). 尽管已经有很多现存的模块使用类似于CapWords.py这样的命名, 但现在已经不鼓励这样做, 因为如果模块名碰巧和类名一致, 这会让人困扰.

Python之父Guido推荐的规范

TYPE PUBLIC INTERNAL
Modules lower_with_under _lower_with_under
Packages lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() _lower_with_under()
Global/Class Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
Global/Class Variables lower_with_under _lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under

Main

Tip

即使是一个打算被用作脚本的文件, 也应该是可导入的. 并且简单的导入不应该导致这个脚本的主功能(main functionality)被执行, 这是一种副作用. 主功能应该放在一个main()函数中.

在Python中, pydoc以及单元测试要求模块必须是可导入的. 你的代码应该在执行主程序前总是检查 if __name__ == '__main__' , 这样当模块被导入时主程序就不会被执行.

def main():
      ...

if __name__ == '__main__':
    main()

所有的顶级代码在模块导入时都会被执行. 要小心不要去调用函数, 创建对象, 或者执行那些不应该在使用pydoc时执行的操作.

请务必保持代码的一致性

如果你正在编辑代码, 花几分钟看一下周边代码, 然后决定风格. 如果它们在所有的算术操作符两边都使用空格, 那么你也应该这样做. 如果它们的注释都用标记包围起来, 那么你的注释也要这样.

制定风格指南的目的在于让代码有规可循, 这样人们就可以专注于”你在说什么”, 而不是”你在怎么说”. 我们在这里给出的是全局的规范, 但是本地的规范同样重要. 如果你加到一个文件里的代码和原有代码大相径庭, 它会让读者不知所措. 避免这种情况.

]]>
https://zuk.pw/index.php/2018/01/85.html/feed 0
万豪酒店被约谈之后 官网又把台湾城市划入日本 https://zuk.pw/index.php/2018/01/72.html https://zuk.pw/index.php/2018/01/72.html#respond Sat, 20 Jan 2018 11:38:52 +0000 https://zuk.pw/?p=72 中国青年网消息,道歉、关网站、解约外包公司、解雇员工等一系列“整改”后,万豪能否平息众怒还尚待观察。然而,有网友发现,万豪英文版网站竟然将中国台湾“并入”了日本……

日前,万豪酒店集团在发给其中国会员的活动邮件中,把西藏列为了“国家”。就在万豪官方微博几度发声明致歉的同时,其又被指在推特上点赞“藏独”言论。

针对万豪“邮件门”、错误点赞等事件,1月11日,上海市网信办责令万豪对官方中文网站、中文版APP自行关闭一周,开展全面自查整改,彻底清理违法违规信息。上海市网信办将视整改情况再作进一步处理。

而就在万豪中文网站尚在维护期间,有网友发现,在万豪英文版网站页面输入“台”字,下拉菜单中出现中国台湾的“台中市”、“台南市”和“台东(县)”,竟然都被标明所属于日本。观察者网登陆万豪英文版网站,发现确实如此。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

日本东京有台东区,在下拉菜单中有显示,所以“台东区”上方的“台东”并不是指台东区。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

万豪英文版官网截图

此外,除了万豪英文版网站,万豪日文版网站也将中国台湾台中市、台南市和台东县列入日本。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

万豪日文版官网截图

登陆万豪法文版、意大利文版查询,没有出现台中、台南,但台东仍显示为属于日本,推荐的是东京的酒店。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

在英文版与日文版网页上,输入台中市、台南市或台东进行搜索,万豪网站给出的推荐酒店均位于东京。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

这就是万豪“痛定思痛”的结果?网友们表示,万豪有点“扶不起来了”,“这回恐怕是彻底凉了”。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

还有网友对万豪的一而再再而三的“作死”表示,已经不感到愤怒了,只觉得可笑。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

目前,万豪中文简体字版、繁体字版和中文版APP都仍在维护中。

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

《万豪酒店被约谈之后 官网又把台湾城市划入日本》

外交部发言人陆慷曾在12日的例行记者会上强调:“香港、澳门、台湾、西藏都是中国的一部分,这是客观事实,也是国际社会的共识。我们欢迎外国企业来华投资兴业,同时在华经营的外国企业也应当尊重中国的主权和领土完整,遵守中国法律,尊重中国人民民族感情。这也是任何企业到其他国家投资兴业、开展合作最起码的遵循。”

]]>
https://zuk.pw/index.php/2018/01/72.html/feed 0
万豪列台湾西藏为国家及点赞藏独 https://zuk.pw/index.php/2018/01/66.html https://zuk.pw/index.php/2018/01/66.html#respond Fri, 19 Jan 2018 06:26:34 +0000 https://zuk.pw/?p=66 2018年1月11日电万豪又道歉了,还有人相信吗?早前因为给会员发送的邮件中将香港、澳门、台湾以及西藏列为“国家”,万豪1月9日至10日在中国官微连发3条道歉,但在这期间,它又去给“藏独”的推特点了个赞。今天(11日),万豪又道歉了,但网友们并不买账,大骂“两面派”。

刚道歉又给“藏独”点赞,被骂“两面派”

《万豪列台湾西藏为国家及点赞藏独》

推特截图

1月10日凌晨1:09,一家名为“Friends of Tibet”(西藏之友)的推特账号发布“祝贺全球连锁酒店万豪国际将西藏与香港、台湾一起列为‘国家’”的一则推文。

而刚刚才在1月9号于国内发表了致歉声明的“Marriott Rewards”(万豪礼赏)却点赞了这一条“藏独”推文!

《万豪列台湾西藏为国家及点赞藏独》 《万豪列台湾西藏为国家及点赞藏独》
《万豪列台湾西藏为国家及点赞藏独》

根据“Friends of Tibet”的简介,这是一个专门致力于“解放与独立西藏”的推特号!是一个典型的“藏独”号!

前脚才在国内为自己把“西藏、台湾、香港与澳门列为国家”道歉,后脚立刻就打脸去给“藏独”推特号点赞!不得不的说@万豪礼赏 这个“点赞”把它的“脸都打肿了”!

此外,小青还发现这个“藏独”号所发此条推文所配的照片中,万豪国际(Marriortt International)就赫然位列其中!

经过小青查询,这位举牌的人就是万豪国际集团董事会执行主席John Willard Bill Marriott !可见“藏独”与万豪渊源极深!

《万豪列台湾西藏为国家及点赞藏独》

@万豪礼赏微博截图

刚刚,万豪中国官微@万豪礼赏又道歉了!

1月9日,一个“藏独”的推特账号发推“祝贺”万豪酒店将西藏与香港、台湾一起列为“国家”,但是被媒体曝光,在寥寥的点赞中,竟赫然出现了@万豪礼赏的身影。对此,刚刚,万豪礼赏回应称“万豪国际集团尊重中国的主权和领土完整。我们绝不支持任何损害中国主权和领土完整的任何分裂组织。我们对任何可能引起对以上立场误解的行为深刻道歉。”海外网发现,截至目前,首页已被4条“道歉”刷屏。

@万豪礼赏微博评论截图。

这种“道歉”再多,广大网友并不买账,清一色大骂其“两面派”。网友质问,“中国微博道歉,美国推特点赞藏独,两面派吗?”“两面三刀,令人恶心,以为国人看不到你在外面点赞吗? ”;还有网友讽刺,“万豪,你认识乐天嘛?”

曾将港澳台及西藏列为“国家”引众怒

据早前报道,万豪酒店近日在给中国会员发送的一份问卷中,竟然在“国家”选项中,将香港、澳门、台湾以及西藏列为“国家”。此举立刻引起了中国会员的不适。

《万豪列台湾西藏为国家及点赞藏独》

《万豪列台湾西藏为国家及点赞藏独》 《万豪列台湾西藏为国家及点赞藏独》 《万豪列台湾西藏为国家及点赞藏独》
《万豪列台湾西藏为国家及点赞藏独》 《万豪列台湾西藏为国家及点赞藏独》

网友微博截图。

随着时间持续发酵,“仲举扫地”也获得了更多网友提供的信息。仲举扫地发现,将“西藏”列为“国家”这一错误竟只在万豪的中文版邮件中存在,其英文版邮件中列出的“国家”选项中,并不存在“西藏”这一选项。

网友发现,如果点开的是万豪问卷的英文版,国家列表中却不仅没有西藏,就连港澳台也都不在上面,名单上涉及中国的只有一个“People’s Republic of China”(即“中华人民共和国”)。

《万豪列台湾西藏为国家及点赞藏独》

如上图所示,整个T字幕开头的区域都没有Taiwan台湾和Tibet西藏

不仅如此,万豪集团在其北美区和英国区的网站都把西藏、香港和澳门也都是归到中国范围内的,只有台湾是与中国并列的,但这个列表倒也没说他们列出的是“国家”,还是酒店所在的“Destination”(即“目的地”)。

而且其英国区的网站在关于中国的介绍部分,还特别写明了西藏是中国的一部分。

《万豪列台湾西藏为国家及点赞藏独》

因此,从现有证据来看,引起中国舆论关注的“港澳台和西藏”被万豪有奖问卷活动列为“国家”的事件,更像是万豪中国方面“单方面”惹出的。因为万豪国际版的网站上并没有出现类似的问题。

只在对中国用户发送的中文版邮件中把“西藏”成为“国家”,这让中国网友们更为气愤,不少网友谴责其“心怀鬼胎”、“恶心人”。截止1月9日晚8点,“仲举扫地”就该事件的微博转发量已超过16000条。

对于该事件产生的原因,万豪公关部门工作人员表示,是系统错误所造成。当记者进一步询问为何仅有中文版邮件中将“西藏”列为“国家”,该工作人员并未给出回应,仅回复称:“对于此事,我们深感抱歉,真诚的抱歉。”

尽管万豪方面已宣称“第一时间修改调查选项”,但记者查看万豪APP会员注册页面发现,在“国家”选项栏中,“香港”、“澳门”、“台湾”这些选项仍然在列。

@万豪礼赏 也在9日下午于微博上做出回应,向“中国会员”致歉。只是该回应被普遍认为“不痛不痒、缺乏诚意”。

10日上午,万豪国际集团今晨在微博@万豪礼赏 上发布声明称:

“对于万豪礼赏会员调查问卷的错误, 我们深表歉意。在发现错误后,所有问卷调查已经被立即终止。我们已采取措施确保类似错误不再发生。万豪国际集团在此重申我们尊重中国主权和领土完整的一贯立场。 ”

然而这样的道歉声明很难令人满意,甚至不少网友指出,这样的道歉毫无诚意。

网友“尺火”发现,“万豪礼赏”并不是万豪酒店的微博大号,粉丝数仅有6万人。他表示:“在一个只有6万粉丝的微博上发声明,而不是@万豪酒店及度假酒店 ,感觉没啥诚意。”

网友“Leo-霍山”则发现,在更早的一则道歉声明中,“万豪礼赏”仅仅是在向会员道歉。

《万豪列台湾西藏为国家及点赞藏独》

@Leo-霍山 表示 “我没有看出你们在对待伤害中国人民感情这件事情上有任何悔悟!单列西藏就是政治挑衅,必须正面道歉!刚看了其微博小号的声明,一为何只对会员致歉?你伤害了中国人民!二是声明为何不是官方微博?你压根就没把此事放在心上,此声明是糊弄大众!@万豪酒店及度假酒店 @万豪礼赏”

10日晚间,@万豪礼赏微博又发媒体声明称,已经对网站和APP内容进行自检。

1月10日,@上海黄浦发布情况通报,称已经约谈万豪酒店管理公司上海负责人及万豪国际集团大中华区负责人,要求万豪国际酒店立即撤下所涉内容,同时对网站和APP上发布的所有信息进行全面检查,杜绝出现类似内容;要求万豪国际酒店及时回应公众关切,通过多种渠道发布改正声明,尽最大努力消除不良影响。

1月11日,澎湃新闻从监管部门获悉,目前,黄浦区市场监管局已对此事立案调查。继1月9日、10日约谈后,案件于11日进入办案取证流程。这一案件不仅涉嫌违法,还涉及国家主权。若查实,将按最严标准处理。

1月11日,新华网以《万豪被查!此事关乎中国主权,不容挑战和触犯!》为题发文,报道了关于此事的最新通报。

]]>
https://zuk.pw/index.php/2018/01/66.html/feed 0
Android 源码编译运行指南(清华aosp) https://zuk.pw/index.php/2018/01/50.html https://zuk.pw/index.php/2018/01/50.html#respond Thu, 18 Jan 2018 11:26:59 +0000 https://zuk.pw/?p=50 《Android 源码编译运行指南(清华aosp)》

源码下载

1 镜像地址

清华大学AOSP(Android Open Source Project)
https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/12

2 过程摘录

下载Repo 工具

mkdir ~/bin
PATH=~/bin:$PATH
curl https://aosp.tuna.tsinghua.edu.cn/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo1234

替换已有的 AOSP 源代码的 remote

如果你之前已经通过某种途径获得了 AOSP 的源码(或者你只是 init 这一步完成后), 你希望以后通过 TUNA 同步 AOSP 部分的代码,只需要将.repo/manifest.xml 把其中的 aosp 这个 remote 的 fetch 从 https://android.googlesource.com 改为 https://aosp.tuna.tsinghua.edu.cn/

<manifest>

   <remote  name="aosp"
-           fetch="https://android.googlesource.com"
+           fetch="https://aosp.tuna.tsinghua.edu.cn"
            review="android-review.googlesource.com" />

   <remote  name="github"

同时,修改 .repo/manifests.git/config,将

url = https://android.googlesource.com/platform/manifest

更改为

url = https://aosp.tuna.tsinghua.edu.cn/platform/manifest

然后在 .repo/manifests 目录下,执行

git add .
git commit -m "change repo mirror"

使用每月更新的初始化包

由于首次同步需要下载 24GB 数据,过程中任何网络故障都可能造成同步失败,我们强烈建议您使用初始化包进行初始化。下载 https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar,下载完成后记得根据 checksum.txt 的内容校验一下。由于所有代码都是从隐藏的 .repo 目录中 checkout 出来的,所以我们只保留了 .repo 目录,下载后解压 再 repo sync 一遍即可得到完整的目录。

使用方法如下:

wget https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar # 下载初始化包 # 实践证明这个也需要改源代码的remote
tar xf aosp-latest.tar
cd AOSP   # 解压得到的 AOSP 工程目录
# 这时 ls 的话什么也看不到,因为只有一个隐藏的 .repo 目录
repo sync # 正常同步一遍即可得到完整目录 #需跨越长城
# 或 repo sync -l 仅checkout代码

此后,每次只需运行 repo sync 即可保持同步。 我们强烈建议您保持每天同步,并尽量选择凌晨等低峰时间

3 解决repo sync下载代码时提示error: Exited sync due to fetch errors

再次执行 repo sync 就可以了

4 其他

  • 初始化包大小21.4G,我的网速5-6M/s,下载时间基本一个小时左右。
  • Android7.0,aosp目录编译完之后的大小是54.6G,安装Ubuntu时要注意留够足够的空间,推荐100G+以上。

源码编译

1 搭建编译环境

  • openJdk is needed !我自己平时开发用的是JDK1.7,这里就要安装一下openjdk,并且更改环境变量。
sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update
sudo apt-get install openjdk-7-jdk

但是如果你是刚安装完Ubuntu,那么就可以跳过此步骤,Ubuntu自带openjdk

  • 写入JAVA_HOME(openjdk的安装路径)给系统配置文件 .bashrc;
echo export JAVA_HOME="/usr/lib/jvm/java-7-openjdk-amd64/" >> ~/.bashrc
source ~/.bashrc

重新输入echo $JAVA_HOME命令,就可以看到刚刚设置好的配置。

  • required package
sudo apt-get install bison g++-multilib git gperf libxml2-utils make python-networkx zlib1g-dev:i386 zip1
  • 因为源码包含C 和 C++代码,gcc为必须
sudo apt-get install gcc1
  • Setting up ccache , 使用ccache

ccache是一个编译器ccache用于C和C++。可以让构建更加快速。在源代码的根目录处,做如下操作:

$export USE_CCACHE=1
$export CCACHE_DIR=/<path_of_your_choice>/.ccache
$prebuilts/misc/linux-x86/ccache/ccache -M 50G</path_of_your_choice>123

建议的cache大小为50-100G

可以使用如下操作来查看使用的ccache大小

$watch -n1 -d prebuilts/misc/linux-x86/ccache/ccache -s1

若使用Ice Cream Sandwich(4.0.x)或更老的版本,需要用prebuilts来代替prebuilts/misc

2 开始编译 Building the System

  • 1.Set up environment
$ source build/envsetup.sh

or

$ . build/envsetup.sh1
  • 2.Choose a Target
$ lunch 

You're building on Linux

Lunch menu... pick a combo:
     1. aosp_arm-eng
     2. aosp_arm64-eng
     3. aosp_mips-eng
     4. aosp_mips64-eng
     5. aosp_x86-eng
     6. aosp_x86_64-eng
     7. aosp_manta-userdebug
     8. aosp_flo-userdebug
     9. aosp_deb-userdebug
     10. full_fugu-userdebug
     11. aosp_fugu-userdebug
     12. aosp_tilapia-userdebug
     13. aosp_grouper-userdebug
     14. aosp_mako-userdebug
     15. aosp_hammerhead-userdebug
     16. aosp_flounder-userdebug
     17. aosp_shamu-userdebug
     18. mini_emulator_x86-userdebug
     19. mini_emulator_arm64-userdebug
     20. mini_emulator_x86_64-userdebug
     21. mini_emulator_mips-userdebug
     22. m_e_arm-userdebug

Which would you like? [aosp_arm-eng] 
  • 3.build

使用make构建,GNU make可以通过使用-jN参数来处理并行任务。此处的N,根据所用的计算机的硬件的核数来指定,一般N指定为CPU核心的1到2倍。例如我的CPU是i5-6500(CPU4个核,每个核2个线程),那么最优的构建是使用make -j8。

make -j8

3 build successfully

#### make completed successfully (01:04:27 (hh:mm:ss)) ####1
  • 目录结构如下:
  7    9月  24 00:36 android-info.txt
  62   9月  24 00:22 build_fingerprint.txt
  4.0K 9月  24 10:34 cache
  66M  9月  24 12:26 cache.img
  70K  9月  23 23:51 clean_steps.mk
  38   9月  24 00:22 current_build_config.mk
  4.0K 9月  24 10:41 data
  4.0K 9月  24 09:51 dex_bootjars
  4.0K 9月  24 01:33 gen
  1.4K 9月  24 12:25 hardware-qemu.ini
  70K  9月  24 11:00 installed-files.txt
  1.1M 9月  24 00:30 module-info.json
  4.0K 9月  24 11:00 obj
  38   9月  23 23:51 previous_build_config.mk
  1.5M 9月  24 10:40 ramdisk.img
  4.0K 9月  24 10:39 recovery
  4.0K 9月  24 10:39 root
  4.0K 9月  24 10:39 symbols
  4.0K 9月  24 10:50 system
  1.8G 9月  24 11:01 system.img
  550M 9月  24 10:58 userdata.img
  550M 9月  24 12:41 userdata-qemu.img
  ~/aosp/out/target/product/generic$ 

4 编译中的问题解决

  • 第一次编译,在编译到82%的时候失败,报错 : Increase Java heap size
including ./tools/external/fat32lib/Android.mk ...  
Starting build with ninja  
ninja: Entering directory `.'  
[  0% 1/21542] Ensure Jack server is installed and started  
Jack server already installed in "/home/smile/.jack-server"  
Server is already running  
[  0% 2/21542] Building with Jack: out/target/common/obj/JAVA_LIBRARIES/core-all_intermediates/with-local/classes.dex  
FAILED: /bin/bash out/target/common/obj/JAVA_LIBRARIES/core-all_intermediates/with-local/classes.dex.rsp  
Java heap space  
Try increasing heap size with java option '-Xmx<size>'  
Warning: This may have produced partial or corrupted output.  
ninja: build stopped: subcommand failed.  
build/core/ninja.mk:146: recipe for target 'ninja_wrapper' failed  
make: *** [ninja_wrapper] Error 1  

#### make failed to build some targets (08:25 (mm:ss)) ####  12345678910111213141516

stackoverflow上关于此问题的解决方法(详见这里),在make之前进行heap size配置

1. export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m"  
2. out/host/linux-x86/bin/jack-admin kill-server  
3. out/host/linux-x86/bin/jack-admin start-server  123

参考链接

下载Android源代码错误汇总分析

Android源码编译详解【三】:Ubantu 服务器的搭载与配置

清华大学 Android 镜像使用帮助

Android7.0源码编译运行指南

android代号、标记和细分版本号

搭建Android 7.0的源码环境

Android FrameWork学习(一)Android 7.0系统源码下载\编译

]]>
https://zuk.pw/index.php/2018/01/50.html/feed 0
Markdown认识与入门 https://zuk.pw/index.php/2017/11/20.html https://zuk.pw/index.php/2017/11/20.html#respond Mon, 27 Nov 2017 10:35:15 +0000 http://www.hosea.pw/?p=20 主要内容

Markdown是什么

发明了这么个东西?

为什么要使用它?

怎么使用?

在用?

感觉有意思?不怕你看见,就怕你试试

正文

1. Markdown是什么

Markdown是一种轻量级标记语言,它以纯文本形式(易读、易写、易更改)编写文档,并最终以HTML格式发布。
Markdown也可以理解为将以MARKDOWN语言编写的语言转换成HTML内容的工具,最初是一个perl脚本Markdown.pl

2. 发明了这么个东西?

它由Aaron SwartzJohn Gruber共同设计,Aaron Swartz就是那位于去年(2013年1月11日)自杀,有着开挂一般人生经历的程序员。维基百科对他的介绍是:软件工程师、作家、政治组织者、互联网活动家、维基百科人

他有着足以让你跪拜的人生经历:
+ 14岁参与RSS 1.0规格标准的制订。
+ 2004年入读斯坦福,之后退学。
+ 2005年创建Infogami,之后与Reddit合并成为其合伙人。
+ 2010年创立求进会(Demand Progress),积极参与禁止网络盗版法案(SOPA)活动,最终该提案居然被撤回。
+ 2011年7月19日,因被控从MIT和JSTOR下载480万篇学术论文并以免费形式上传于网络被捕。
+ 2013年1月自杀身亡。

《Markdown认识与入门》

天才都有早逝的归途(又是一位犹太人)。

3. 为什么要使用它?

  • 它是易读(看起开舒服)、易写(语法简单)、易更改纯文本。处处体现着极简主义的影子。
  • 兼容HTML,可以转换为HTML格式发布。
  • 跨平台使用。
  • 越来越多的网站支持Markdown。
  • 更方便清晰的组织你的电子邮件。(Markdown-here, Airmail)
  • 摆脱Word(我不是认真的)。

4. 怎么使用?

如果不算扩展,Markdown的语法绝对简单到让你爱不释手。

废话太多,下面正文,Markdown语法主要分为如下几大部分:
标题段落区块引用代码区块强调列表分割线链接图片反斜杠 \符号’`’

4.1 标题

两种形式:
1)使用=-标记一级和二级标题。

一级标题
=========
二级标题
---------

效果:

一级标题

二级标题

2)使用#,可表示1-6级标题。

# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题

效果:

一级标题

二级标题

三级标题

四级标题

五级标题
六级标题

4.2 段落

段落的前后要有空行,所谓的空行是指没有文字内容。若想在段内强制换行的方式是使用两个以上空格加上回车(引用中换行省略回车)。

4.3 区块引用

在段落的每行或者只在第一行使用符号>,还可使用多个嵌套引用,如:

> 区块引用
>> 嵌套引用

效果:

区块引用

嵌套引用

4.4 代码区块

代码区块的建立是在每行加上4个空格或者一个制表符(如同写代码一样)。如
普通段落:

void main()
{
printf(“Hello, Markdown.”);
}

代码区块:

void main()
{
    printf("Hello, Markdown.");
}

注意:需要和普通段落之间存在空行。

4.5 强调

在强调内容两侧分别加上*或者_,如:

*斜体*,_斜体_
**粗体**,__粗体__

效果:

斜体斜体
粗体粗体

4.6 列表

使用·+、或-标记无序列表,如:

-(+*) 第一项
-(+*) 第二项
- (+*)第三项

注意:标记后面最少有一个空格制表符。若不在引用区块中,必须和前方段落之间存在空行。

效果:

  • 第一项
  • 第二项
  • 第三项

有序列表的标记方式是将上述的符号换成数字,并辅以.,如:

1 . 第一项
2 . 第二项
3 . 第三项

效果:

  1. 第一项
  2. 第二项
  3. 第三项

4.7 分割线

分割线最常使用就是三个或以上*,还可以使用-_

4.8 链接

链接可以由两种形式生成:行内式参考式
行内式

[hoseahsu的github库](https://github.com/hoseahsu “Markdown”)。

效果:

hoseahsu的github库

参考式

[hoseahsu的github库1][1]
[hoseahsu的github库2][2]
[1]:https://github.com/hoseahsu “Markdown”
[2]:https://github.com/hoseahsu “Markdown”

效果:

hoseahsu的github库1
hoseahsu的github库2

注意:上述的[1]:https://github.com/hoseahsu "Markdown"不出现在区块中。

4.9 图片

添加图片的形式和链接相似,只需在链接的基础上前方加一个

4.10 反斜杠\

相当于反转义作用。使符号成为普通符号。

4.11 符号’`’

起到标记作用。如:

`ctrl+a`

效果:

ctrl+a

5. 在用?

Markdown的使用者:
+ GitHub
+ 简书
+ Stack Overflow
+ Apollo
+ Moodle
+ Reddit
+ 有道云笔记
+ CSDN
+ 等等

6. 感觉有意思?趁热打铁,推荐几个工具

  • Chrome下的stackedit插件可以离线使用,很爽。也不用担心平台受限。
    在线的dillinger.io算是评价好的了,可是不能离线使用。
  • Windowns下的MarkdownPad也用过,不过免费版的体验不是很好。
  • Mac下的Mou是国人贡献的,口碑很好。推荐。
  • Linux下的ReText不错。

其实在对语法了如于心的话,直接用编辑器就可以了,脑子里满满的都是格式化好的文本啊。
我现在使用马克飞象 + Markdown-here,先编辑好,然后一键格式化,挺方便。


注意:不同的Markdown解释器或工具对相应语法(扩展语法)的解释效果不尽相同,具体可参见工具的使用说明。
虽然有人想出面搞一个所谓的标准化的Markdown,[没想到还惹怒了健在的创始人John Gruber]
(http://blog.codinghorror.com/standard-markdown-is-now-common-markdown/)。


以上基本是所有traditonal markdown的语法。

其它:

列表的使用(非traditonal markdown):

|表示表格纵向边界,表头和表内容用-隔开,并可用:进行对齐设置,两边都有:则表示居中,若不加:则默认左对齐。

代码库 链接
configuration https://github.com/hoseahsu/configuration
donate2me https://github.com/hoseahsu/donate2me

关于其它扩展语法可参见具体工具的使用说明。

]]>
https://zuk.pw/index.php/2017/11/20.html/feed 0
程序员整理的各种不错的工具 https://zuk.pw/index.php/2017/11/23.html https://zuk.pw/index.php/2017/11/23.html#respond Mon, 27 Nov 2017 09:39:46 +0000 http://www.hosea.pw/?p=23 技术站点
  • Hacker News:非常棒的针对编程的链接聚合网站
  • Programming reddit:同上
  • MSDN:微软相关的官方技术集中地,主要是文档类
  • infoq:企业级应用,关注软件开发领域
  • OSChina:开源技术社区,开源方面做的不错哦
  • cnblogs,51cto,csdn:常见的技术社区,各有专长
  • stackoverflow:IT技术问答网站
  • GitHub:全球最大的源代码管理平台,很多知名开源项目都在上面,如Linux内核,
  • OpenStack等免费的it电子书:http://it-ebooks.info/
  • DevStore:开发者服务商店

不错的书籍

  • 人件
  • 人月神话
  • 代码大全2
  • 计算机程序设计艺术
  • 程序员的自我修养
  • 程序员修炼之道
  • 高效能程序员的修炼(成为一名杰出的程序员其实跟写代码没有太大关系)
  • 深入理解计算机系统
  • 软件随想录
  • 算法导论(麻省理工学院出版社)
  • 离线数学及其应用
  • 设计模式
  • 编程之美
  • 黑客与画家
  • 编程珠玑
  • C++ Prime
  • Effective C++
  • TCP/IP详解
  • Unix 编程艺术
  • 《精神分析引论》弗洛伊德
  • 搞定:无压力工作的艺术

平台工具(都是开源的好东东哦)

  • Redmine/Trac:项目管理平台
  • Jenkins/Jira(非开源):持续集成系统(Apache Continuum,这个是Apache下的CI系统,还没来得及研究)
  • Sonar:代码质量管理平台
  • git,svn:源代码版本控制系统
  • GitLib/Gitorious:构建自己的GitHub服务器
  • gitbook:https://www.gitbook.io/写书的好东西,当然用来写文档也很不错的
  • Travis-ci:开源项目持续集成必备,和GitHub相结合,https://travis-ci.org/
  • 开源测试工具、社区(Selenium、OpenQA.org)
  • Puppet:一个自动管理引擎,可以适用于Linux、Unix以及Windows平台。所谓配置管理系统,就是管理机器里面诸如文件、用户、进程、软件包这些资源。无论是管理1台,还是上万台机器Puppet都能轻松搞定。
  • Nagios:系统状态监控报警,还有个Icinga(完全兼容nagios所有的插件,工作原理,配置文件以及方法,几乎一模一样。配置简单,功能强大)
  • Ganglia:分布式监控系统
  • fleet:分布式init系统

爬虫相关(好玩的工具)

  • Phantomjs
  • berserkJS(基于Phantomjs的改进版本)
  • SlimerJS
  • CasperJS
  • selenium

Web 服务器性能/压力测试工具/负载均衡器

  • http_load: 程序非常小,解压后也不到100K
  • webbench: 是Linux下的一个网站压力测试工具,最多可以模拟3万个并发连接去测试网站的负载能力
  • ab: ab是apache自带的一款功能强大的测试工具
  • Siege: 一款开源的压力测试工具,可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。
  • squid(前端缓存),nginx(负载),nodejs(没错它也可以,自己写点代码就能实现高性能的负载均衡器):常用的负载均衡器
  • Piwik:开源网站访问量统计系统
  • ClickHeat:开源的网站点击情况热力图
  • HAProxy:高性能TCP /HTTP负载均衡器
  • ElasticSearch:搜索引擎基于Lucene
  • Page Speed SDK和YSLOW
  • HAR Viewer: HAR分析工具
  • protractor:E2E(end to end)自动化测试工具

Web 前端相关

  • GRUNT: js task runner
  • js: js模块化
  • js:MVVM开发前台,绑定技术
  • js: 使用超动感HTML & JS开发WEB应用!
  • js,Flot:常用的Web图表插件
  • Raw:非常不错的一款高级数据可视化工具
  • Rickshaw:时序图标库,可用于构建实时图表
  • JavaScript InfoVis Toolkit:另一款Web数据可视化插件
  • js,在html中展现pdf
  • ACE,CodeMirror:Html代码编辑器(ACE甚好啊)
  • NProcess:绚丽的加载进度条
  • js:让你制作出令人眩目的内容展示效果(类似的还有reveal)
  • Threejs:3DWeb库
  • Hightopo:基于Html5的2D、3D可视化UI库
  • dataTables.js:高度灵活的表格插件
  • Raphaël:js,canvas绘图库,后来发现百度指数的图形就是用它绘出来的
  • js:js路由模块,前端路由,Nodejs后端路由等,适合构造单页应用
  • js:页面加载进度条
  • bower:Web包管理器
  • jsnice:有趣的js反编译工具,猜压缩后的变量名 http://www.jsnice.org/
  • js: 是一个基于JavaScript数据展示库(类似的还有P5.js)
  • js:移动端替代jQuery的东东,当然也可以使用jquery-mobile.

UI框架:Foundation,Boostrap,Pure,EasyUI,Polymer

前端UI设计师必去的几个网站:Dribbble,awwwards,unmatchedstyle,UIMaker

Mozilla 开发者中心:https://developer.mozilla.org/en-US/

图标资源:IcoMoon(我的最爱),Themify Icons,FreePik,Glyphiconsart

  • Dialog:非常漂亮的对话框
  • AdminLTE:github上的一个开源项目,基于Boostrap3的后台管理页面框架
  • js:让不懂爱的IE6-8支持响应式设计
  • js: js模块加载库
  • select2:比chosen具有更多特性的选择框替代库
  • AngularUI:集成angular.js的UI库
  • css: 采用了现代化标准让各浏览器渲染出的html保持一致的库
  • CreateJS:Html5游戏引擎Less,Compass:简化CSS开发
  • js:用于自动识别网页上的Emoji文字并将其显示为图像
  • simditor:一个不错的开源的html编辑器,简洁高效
  • Sencha: 基于html5的移动端开发框架
  • SuperScrollorama+TweenMax+skrollr:打造超酷的视差滚动效果网页动画
  • jquery-smooth-scroll:同上,平滑滚动插件
  • css:实现了各种动画效果的css库
  • Emmet:前端工程师必备,ZenCode的前身
  • MagicDraw:Uml图工具

大数据处理/数据分析/分布式工具

  • Hadoop:分布式的文件系统,结合其MapReduce编程模型可以用来做海量数据的批处理( Hive,Pig, Hbase啥的就不说了),值得介绍的是Cloudera的Hadoop分支CDH5,基于YARN MRv2集成了 Spark可直接用于生产环境的Hadoop,对于企业快速构建数据仓库非常有用。
  • Ceph: Linux分布式文件系统(特点:无中心)
  • Storm:实时流数据处理,可以看下IBM的一篇介绍 (还有个Yahoo的S4,也是做流数据处理的)
  • Spark:大规模流式数据处理(可以应付企业中常见的三种数据处理场景:复杂的批量数据处理(batch data processing);基于历史数据的交互式查询(interactive query);基于实时数据流的数据处理(streaming data processing)),CSND有篇文章介绍的不错
  • Spark Streaming:基于Spark的实时计算框架
  • Tachyon:分布式内存文件系统
  • Mesos:计算框架一个集群管理器,提供了有效的、跨分布式应用或框架的资源隔离和共享Impala:新一代开源 大数据分析引擎,提供Sql语义,比- Hive强在速度上
  • SNAPPY:快速的数据压缩系统,适用于Hadoop生态系统中
  • Kafka:高吞吐量的分布式消息队列系统
  • ActiveMQ:是Apache出品,最流行的,能力强劲的开源消息总线
  • MQTT:Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分
  • RabbitMQ:记得 OpenStack就是用的这个东西吧
  • ZeroMQ:宣称是将分布式计算变得更简单,是个分布式消息队列,可以看下云风的一篇文章的介绍开源的日志收集系统:scribe、chukwa、kafka、flume。这有一篇对比文章
  • Zookeeper:可靠的分布式协调的开源项目
  • Databus:LinkedIn 实时低延迟数据抓取系统

数据源获取:Flume、Google Refine、Needlebase、ScraperWiki、BloomReach

序列化技术:JSON、BSON、Thrift、Avro、Google Protocol Buffers

NoSql:Apache Hadoop、Apache Casandra、 MongoDB、Apache CouchDB、 Redis、BigTable、HBase、Hypertable、Voldemort、Neo4j

MapReduce相关:Hive、Pig、Cascading、Cascalog、mrjob、Caffeine、S4、MapR、Acunu、Flume、Kafka、Azkaban、Oozie、Greenplum

数据处理:R、Yahoo! Pipes、Mechanical Turk、Solr/ Lucene、ElasticSearch、Datameer、Bigsheets、TinkerpopNLP自然语言处理:Natural Language Toolkit、Apache OpenNLP、Boilerpipe、OpenCalais

机器学习:WEKA、Mahout、scikits.learn、SkyTree

可视化技术:GraphViz、Processing、Protovis、Google Fusion Tables、Tableau、Highcharts、EChats(百度的还不错)、Raphaël.js

  • Kettle:开源的ETL工具
  • Pentaho:以工作流为核心的开源BI系统
  • Mondrian:开源的Rolap服务器
  • Oozie:开源hadoop的工作流调度引擎

开源的数据分析可视化工具:Weka、Orange、KNIME

Cobar:阿里巴巴的 MySQL分布式中间件

C & C++

Thrift:用来进行可扩展且跨语言的服务的开发(类似的还有个Avro,Google protobuf)。

libevent:是一个事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue等系统调用管理事件机制。(对了还有个libev呢)

Boost:不多说了,准C++标准库

Ptmalloc\Valgrind\Purify

NetworkServer 架构:acceptor->dispatcher->worker(这个不算工具哦)

breakpad:崩溃转储和分析模块,很多crashreport会用到

UI界面相关:MFC、BCG和QT这类的就不说了,高端一点的还有Html和DirectUI技术:libcef(基于chrome内核的,想想使用 HTML5开发页面,还真有点小激动呢)、HtmlLayout、Duilib、Bolt,非C++的,还有node-webkit也不错,集成了node和webkit内核。

游戏开发相关

MINA:使用 Java开发手游和页游服务器(对了还有Netty,也很猛的,都是基于NIO的)

HP-Socket:见有有些页游服务器使用这个构建的

云风的技术博客:http://blog.codingnow.com/

OGRE:大名鼎鼎的3D图形渲染引擎

OpenVDB:梦工厂C++的特效库,开源的

cocos2d:跨平台2D游戏引擎

Unity3D:跨平台3D游戏引擎,很火的哦

Nodejs:也有不少使用它来开发手游和也有服务器(网易的Pomelo就是哦)

日志聚合,分布式日志收集

Scribe:Facebook的(nodejs + scribe + inotify 同步日志)

logstash:强大的日志收集系统,可以基于logstash+kibana+elasticsearch+redis开发强大的日志分析平台

log.io: nodejs开发的实时日志收集系统

RTP,实时传输协议与音视频

RTP,RTCP,RTSP-> librtp,JRTPLIB(遵循了RFC1889标准)

环形缓冲区,实时数据传输用

SDL,ffmpeg,live555,Speex

Red5:用Java开发开源的Flash流媒体服务器。它支持:把音频(MP3)和视频(FLV)转换成播放流; 录制客户端播放流(只支持FLV);共享对象;现场直播流发布;远程调用。

Python

Eric,Eclipse+pydev,比较不错的 Python IDE

PyWin:Win32 api编程包

numpy:科学计算包,主要用来处理大型矩阵计算等,此外还有SciPy,Matplotlib

GUI相关:PyQt,PyQwt

supervisor:进程监控工具

Java相关

常用的IDE:IntelliJ IDEA,Eclipse,Netbeans

Web开发相关:Tomcat、Resin、Jetty、WebLogic等,常用的组件Struts, spring

HibernateNetty: 异步事件驱动网络应用编程框架,用于高并发网络编程比较好(NIO框架)

MINA:简单地开发高性能和高可靠性的网络应用程序(也是个NIO框架),不少手游服务端是用它开发的

jOOQ: Java Orm框架Activiti:工作流引擎,类似的还有jBPM、Snaker

Perfuse:是一个用户界面包用来把有结构与无结构数据以具有交互性的可视化图形展示出来.

Gephi:复杂网络分析软件, 其主要用于各种网络和复杂系统,动态和分层图的交互可视化与探测开源工具

Nutch:知名的爬虫项目,hadoop就是从这个项目中发展出来的

web-harvest:Web数据提取工具

POM工具:Maven+ArtifactoryNetflix

Curator:Netflix公司开源的一个Zookeeper client library,用于简化Zookeeper客户端编程

Akka:一款基于actor模型实现的 并发处理框架

EclEmma:覆盖 测试工具

.net相关

Xilium.CefGlue:基于CEF框架的.NET封装,基于.NET开发Chrome内核浏览器

CefSharp:同上,有一款WebKit的封装,C#和Js交互会更简单

netz:免费的 .NET 可执行文件压缩工具

SmartAssembly:变态的.net代码优化混淆工具

NETDeob0:.net反混淆工具,真是魔高一尺道高一丈啊(还有个de4dot,在GitHub上,都是开源的)

ILMerge:将所有引用的DLL和exe文件打成一个exe文件

ILSpy:开源.net程序反编译工具

JavaScript.NET:很不错的js执行引擎,对v8做了封装

NPOI: Excel操作

DotRAS:远程访问服务的模块

WinHtmlEditor: Winform下的html编辑器

SmartThreadPool:使用C#实现的,带高级特性的线程池

Snoop: WPF Spy Utility

Autofac: 轻量级IoC框架

HtmlAgilityPack:Html解析利器

Quartz .NET:Job调度

HttpLib:@CodePlex,简化http请求

SuperSocket:简化Socket操作,基于他的还有个SuperWebSocket,可以开发独立的WebSocket服务器了

DocX:未安装Office的情况下操作Word文件

Dapper:轻量级的ORM类,性能不错

HubbleDotNet:支持接入 数据库的全文搜索系统

fastJSON:@CodeProject,高性能的json序列化类

ZXing .Net:@CodePlex,QR,条形码相关

Nancy:轻量级Http服务器,做个小型的Web应用可以摆脱IIS喽(Nancy.Viewengines.Razor,可以加入Razor引擎)

AntiXSS:微软的XSS防御库Microsoft Web Protection

LibraryJint:JavaScript解释器

CS-Script:将C#代码文件作为脚本执行

Jexus:Linux下 高性能、易用、免费的ASP.NET服务器

Clay:将dynamic发挥的更加灵活,像写js一样写C#

DynamicJSON:不必定义数据模型获取json数据

Antlr:开源的语法分析器(归到C#不太合适,其他语言也可以去用)

SharpPcap:C#版的WinPcap调用端,牛逼的网络包分析库(自带PacketNotNet用于包协议分析)

Roslyn:C#,VB编译器

ImageResizer: 服务端自由控制图片大小,真乃神器也,对手机端传小图,PC端传大图,CMS用它很方便

UI相关:DevExpress, Fluent(Office 07风格), mui(Modern UI for WPF)

NetSparkle:应用自动更新组件

ConfuserEx: 开源.net混淆工具

ServiceStack: 开源高性能Web服务框架,可用于构建高性能的REST服务Expression

Evaluator:Eval for C#,处理字符串表达式

http://nugetmusthaves.com/

常用工具

  • Fiddler:非常好用的Web前端调试工具,当然是针对底层http协议的,一般情况使用Chrome等自带的调试工具也足够了,特殊情况还得用它去处理
  • wireshark:知名的网络数据包分析工具
  • PowerCmd:替代Windows Cmd的利器
  • RegexBuddy:强大的正则表达式测试工具
  • Soure Insight:源代码阅读神器
  • SublimeText:程序员最爱的编辑器
  • NET:一个通用的关系型数据库客户端,基于.NET 4.0开发的,做简单的处理还是蛮方便的
  • Navicat Premium:支持MySql、PostgreSQL、Oracle、Sqlite和SQL Server的客户端,通用性上不如Database.NET,但性能方面比Database.NET好很多,自带备份功能也用于数据库定时备份。
  • Synergy : 局域网内一套键盘鼠标控制多台电脑
  • DameWare:远程协助工具集(我在公司主要控制大屏幕用)
  • Radmin: 远程控制工具,用了一段时间的
  • DameWare,还要破解,对Win7支持的不好,还是发现这个好用
  • Listary:能极大幅度提高你 Windows 文件浏览与搜索速度效率的「超级神器」
  • Clover:给资源管理器加上多标签
  • WinLaunch:模拟Mac OS的Launch工具
  • Fritzing:绘制电路图
  • LICEcap:gif教程制作git,
  • svn:版本控制系统Enigma Virtual Box(将exe,dll等封装成一个可执行程序)
  • Open DBDiff(针对SqlServer)数据库同步
  • SymmetricDS:数据库同步
  • BIEE,Infomatica,SPSS,weka,R语言:数据分析
  • CodeSmith,LightSwitch:代码生成
  • Pandoc:Markdown转换工具,出书用的。以前玩过docbook,不过现在还是Markdown盛行啊。
  • Window Magnet[Mac]:增强Mac窗口管理功能,想Win7一样具有窗口拖放到屏幕边缘自动调整的功能
  • log explorer:查看SqlServer日志dependency
  • walker:查询Windows应用程序dll依赖项
  • Shairport4w:将iPhone,iPad,iPod上的音频通过AirPlay协议传输到PC上
  • ngrok:内网穿透工具Axure:快速原型制作工具,还有个在线作图的工具国内的一个创业团队做的,用着很不错 http://www.processon.com
  • tinyproxy:(Linux)小型的代理服务器支持http和https协议EaseUS Partition
  • Master:超级简单的分区调整工具,速度还是蛮快的,C盘不够用了就用它从D盘划点空间吧,不用重装系统这么折腾哦。
  • CheatEngine:玩游戏修改内存值必备神器(记得我在玩轩辕剑6的时候就用的它,超级方便呢)
  • ApkIDE:Android反编译神器翻、墙工具(自|由|门、天行浏览器)

设计工具:Sketch、OmniGraffle

MindManger:思维导图

]]>
https://zuk.pw/index.php/2017/11/23.html/feed 0
值得学习的C语言开源项目 https://zuk.pw/index.php/2017/11/22.html https://zuk.pw/index.php/2017/11/22.html#respond Mon, 27 Nov 2017 09:37:34 +0000 http://www.hosea.pw/?p=22 – 1. Webbench

Webbench是一个在 Linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL, 测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。Webbench使用 C语言编写, 代码实在太简洁,源码加起来不到600行。

下载链接: http://home.tiscali.cz/~cz210552/webbench.html

– 2. Tinyhttpd

tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),附带一个简单的Client,可以通过阅读这段代码理解一个 Http Server 的本质。

下载链接: http://sourceforge.net/projects/tinyhttpd/

– 3. cJSON

cJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有500多行,速度也非常理想。

cJSON也存在几个弱点,虽然功能不是非常强大,但cJSON的小身板和速度是最值得赞赏的。其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习。

项目主页: http://sourceforge.net/projects/cjson/

– 4. CMockery

cmockery是google发布的用于C单元测试的一个轻量级的框架。它很小巧,对其他开源包没有依赖,对被测试代码侵入性小。cmockery的源代码行数不到3K,你阅读一下will_return和mock的源代码就一目了然了。

主要特点:

  • 免费且开源,google提供技术支持;
  • 轻量级的框架,使测试更加快速简单;
  • 避免使用复杂的编译器特性,对老版本的编译器来讲,兼容性好;
  • 并不强制要求待测代码必须依赖C99标准,这一特性对许多嵌入式系统的开发很有用

下载链接: http://code.google.com/p/cmockery/downloads/list

– 5. Libev

libev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处理这一套框架下处理。基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。

下载链接: http://software.schmorp.de/pkg/libev.html

– 6. Memcached

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻 数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态数据库驱动网站的速度。Memcached 基于一个存储键/值对的 hashmap。Memcached-1.4.7的代码量还是可以接受的,只有10K行左右。

下载地址: http://memcached.org/

– 7. Lua

Lua很棒,Lua是巴西人发明的,这些都令我不爽,但是还不至于脸红,最多眼红。

让我脸红的是Lua的源代码,百分之一百的ANSI C,一点都不掺杂。在任何支持ANSI C编译器的平台上都可以轻松编译通过。我试过,真是一点废话都没有。Lua的代码数量足够小,5.1.4仅仅1.5W行,去掉空白行和注释估计能到1W行。

下载地址: http://www.lua.org/

– 8. SQLite

SQLite是一个开源的 嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。足够小,大致3万行C代码,250K。

下载地址:http://www.sqlite.org/ 。

– 9. UNIX v6

UNIX V6 的内核源代码包括设备驱动程序在内 约有1 万行,这个数量的源代码,初学者是能够充分理解的。有一种说法是一个人所能理解的代码量上限为1 万行,UNIX V6的内核源代码从数量上看正好在这个范围之内。看到这里,大家是不是也有"如果只有1万行的话没准儿我也能学会"的想法呢?

另一方面,最近的 操作系统,例如Linux 最新版的内核源代码据说超过了1000 万行。就算不是初学者,想完全理解全部代码基本上也是不可能的。

下载地址: http://minnie.tuhs.org/cgi-bin/utree.pl?file=V6

– 10. NETBSD

NetBSD是一个免费的,具有高度移植性的 UNIX-like 操作系统,是现行可移植平台最多的操作系统,可以在许多平台上执行,从 64bit alpha 服务器到手持设备和嵌入式设备。NetBSD计划的口号是:"Of course it runs NetBSD"。它设计简洁,代码规范,拥有众多先进特性,使得它在业界和学术界广受好评。由于简洁的设计和先进的特征,使得它在生产和研究方面,都有卓越的表现,而且它也有受使用者支持的完整的源代码。许多程序都可以很容易地通过NetBSD Packages Collection获得。

下载地址: http://www.netbsd.org/

C++ 资源大全

关于 C++ 框架、库和资源的一些汇总列表,内容包括:标准库、Web应用框架、人工 智能、数据库、图片处理、 机器学习、日志、代码分析等。

标准库

C++标准库,包括了STL容器, 算法和函数等。

框架

C++通用框架和库

  • Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合
  • ASL :Adobe源代码库提供了同行的评审和可移植的C++源代码库。
  • Boost :大量通用C++库的集合。
  • BDE :来自于彭博资讯实验室的开发环境。
  • Cinder:提供专业品质创造性编码的开源开发社区。
  • Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。
  • Dlib:使用契约式编程和现代C++科技设计的通用的跨平台的C++库。
  • EASTL :EA-STL公共部分
  • ffead-cpp :企业应用程序开发框架
  • Folly:由Facebook开发和使用的开源C++库
  • JUCE :包罗万象的C++类库,用于开发跨平台软件
  • libPhenom:用于构建高性能和高度可扩展性系统的事件框架。
  • LibSourcey :用于实时的视频流和高性能网络应用程序的C++11 evented IO
  • LibU : C语言写的多平台工具库
  • Loki :C++库的设计,包括常见的设计模式和习语的实现。
  • MiLi :只含头文件的小型C++库
  • penFrameworks :开发C++工具包,用于创意性编码。
  • Qt :跨平台的应用程序和用户界面框架
  • Reason :跨平台的框架,使开发者能够更容易地使用Java,.Net和Python,同时也满足了他们对C++性能和优势的需求。
  • ROOT :具备所有功能的一系列面向对象的框架,能够非常高效地处理和分析大量的数据,为欧洲原子能研究机构所用。
  • STLport:是STL具有代表性的版本
  • STXXL:用于额外的大型数据集的标准模板库。
  • Ultimate++ :C++跨平台快速应用程序开发框架
  • Windows Template Library:用于开发Windows应用程序和UI组件的C++库
  • Yomm11 :C++11的开放multi-methods.

人工智能

  • btsk :游戏行为树启动器工具
  • Evolving Objects:基于模板的,ANSI C++演化计算库,能够帮助你非常快速地编写出自己的随机优化算法。
  • Neu:C++11框架,编程语言集,用于创建人工智能应用程序的多用途软件系统。

异步事件循环

  • Asio:用于网络和底层I/O编程的跨平台的C++库。
  • libev :功能齐全,高性能的时间循环,轻微地仿效libevent,但是不再像libevent一样有局限性,也修复了它的一些bug。
  • libevent :事件通知库
  • libuv :跨平台异步I/O。

音频

音频,声音,音乐,数字化音乐库

  • FMOD :易于使用的跨平台的音频引擎和音频内容的游戏创作工具。
  • Maximilian :C++音频和音乐数字信号处理库
  • OpenAL :开源音频库—跨平台的音频API
  • Opus:一个完全开放的,免版税的,高度通用的音频编解码器
  • Speex:免费编解码器,为Opus所废弃
  • Tonic: C++易用和高效的音频合成
  • Vorbis: Ogg Vorbis是一种完全开放的,非专有的,免版税的通用压缩音频格式。

生态学

生物信息,基因组学和生物技术

  • libsequence:用于表示和分析群体遗传学数据的C++库。
  • SeqAn:专注于生物数据序列分析的算法和数据结构。
  • Vcflib :用于解析和处理VCF文件的C++库
  • Wham:直接把联想测试应用到BAM文件的基因结构变异。

压缩

压缩和归档库

  • bzip2:一个完全免费,免费专利和高质量的数据压缩
  • doboz:能够快速解压缩的压缩库
  • PhysicsFS:对各种归档提供抽象访问的库,主要用于视频游戏,设计灵感部分来自于Quake3的文件子系统。
  • KArchive:用于创建,读写和操作文件档案(例如zip和 tar)的库,它通过QIODevice的一系列子类,使用gzip格式,提供了透明的压缩和解压缩的数据。
  • LZ4 :非常快速的压缩算法
  • LZHAM :无损压缩数据库,压缩比率跟LZMA接近,但是解压缩速度却要快得多。
  • LZMA :7z格式默认和通用的压缩方法。
  • LZMAT :及其快速的实时无损数据压缩库
  • miniz:单一的C源文件,紧缩/膨胀压缩库,使用zlib兼容API,ZIP归档读写,PNG写方式。
  • Minizip:Zlib最新bug修复,支持PKWARE磁盘跨越,AES加密和IO缓冲。
  • Snappy :快速压缩和解压缩
  • ZLib :非常紧凑的数据流压缩库
  • ZZIPlib:提供ZIP归档的读权限。

并发性

并发执行和多线程

  • Compute :用于OpenCL的C++GPU计算库
  • Bolt :针对GPU进行优化的C++模板库
  • C++React :用于C++11的反应性编程库
  • Intel TBB :Intel线程构件块
  • Libclsph:基于OpenCL的GPU加速SPH流体仿真库
  • OpenCL :并行编程的异构系统的开放标准
  • OpenMP:OpenMP API
  • Thrust :类似于C++标准模板库的并行算法库
  • HPX :用于任何规模的并行和分布式应用程序的通用C++运行时系统
  • VexCL :用于OpenCL/CUDA 的C++向量表达式模板库。

容器

  • C++ B-tree :基于B树数据结构,实现命令内存容器的模板库
  • Hashmaps: C++中开放寻址哈希表算法的实现

密码学

  • Bcrypt :一个跨平台的文件加密工具,加密文件可以移植到所有可支持的操作系统和处理器中。
  • BeeCrypt
  • Botan: C++加密库
  • Crypto++:一个有关加密方案的免费的C++库
  • GnuPG: OpenPGP标准的完整实现
  • GnuTLS :实现了SSL,TLS和DTLS协议的安全通信库
  • Libgcrypt
  • libmcrypt
  • LibreSSL:免费的SSL/TLS协议,属于2014 OpenSSL的一个分支
  • LibTomCrypt:一个非常全面的,模块化的,可移植的加密工具
  • libsodium:基于NaCI的加密库,固执己见,容易使用
  • Nettle 底层的加密库
  • OpenSSL : 一个强大的,商用的,功能齐全的,开放源代码的加密库。
  • Tiny AES128 in C :用C实现的一个小巧,可移植的实现了AES128ESB的加密算法

数据库

数据库,SQL服务器,ODBC驱动程序和工具

  • hiberlite :用于Sqlite3的C++对象关系映射
  • Hiredis: 用于Redis数据库的很简单的C客户端库
  • LevelDB: 快速键值存储库
  • LMDB:符合数据库四大基本元素的嵌入键值存储
  • MySQL++:封装了MySql的C API的C++ 包装器
  • RocksDB:来自Facebook的嵌入键值的快速存储
  • SQLite:一个完全嵌入式的,功能齐全的关系数据库,只有几百KB,可以正确包含到你的项目中。

调试

调试库, 内存和资源泄露检测,单元测试

  • Test:Boost测试库
  • Catch:一个很时尚的,C++原生的框架,只包含头文件,用于单元测试,测试驱动开发和行为驱动开发。
  • CppUnit:由JUnit移植过来的C++测试框架
  • CTest:CMake测试驱动程序
  • googletest:谷歌C++测试框架
  • ig-debugheap:用于跟踪内存错误的多平台调试堆
  • libtap:用C语言编写测试
  • MemTrack —用于C++跟踪内存分配
  • microprofile– 跨平台的网络试图分析器
  • minUnit :使用C写的迷你单元测试框架,只使用了两个宏
  • Remotery:用于web视图的单一C文件分析器
  • UnitTest++:轻量级的C++单元测试框架

游戏引擎

  • Cocos2d-x :一个跨平台框架,用于构建2D游戏,互动图书,演示和其他图形应用程序。
  • Grit :社区项目,用于构建一个免费的游戏引擎,实现开放的世界3D游戏。
  • Irrlicht :C++语言编写的开源高性能的实时#D引擎
  • Polycode:C++实现的用于创建游戏的开源框架(与Lua绑定)。

图形用户界面

  • CEGUI : 很灵活的跨平台GUI库
  • FLTK :快速,轻量级的跨平台的C++GUI工具包。
  • GTK+: 用于创建图形用户界面的跨平台工具包
  • gtkmm :用于受欢迎的GUI库GTK+的官方C++接口。
  • imgui:拥有最小依赖关系的立即模式图形用户界面
  • libRocketlibRocket 是一个C++ HTML/CSS 游戏接口中间件
  • MyGUI :快速,灵活,简单的GUI
  • Ncurses:终端用户界面
  • QCustomPlot :没有更多依赖关系的Qt绘图控件
  • Qwt :用户与技术应用的Qt 控件
  • QwtPlot3D :功能丰富的基于Qt/OpenGL的C++编程库,本质上提供了一群3D控件
  • OtterUIOtterUI 是用于嵌入式系统和互动娱乐软件的用户界面开发解决方案
  • PDCurses 包含源代码和预编译库的公共图形函数库
  • wxWidgets C++库,允许开发人员使用一个代码库可以为widows, Mac OS X,Linux和其他平台创建应用程序

图形

  • bgfx:跨平台的渲染库
  • Cairo:支持多种输出设备的2D图形库
  • Horde3D 一个小型的3D渲染和动画引擎
  • magnum C++11和OpenGL 2D/3D 图形引擎
  • Ogre 3D 用C++编写的一个面向场景,实时,灵活的3D渲染引擎(并非游戏引擎)
  • OpenSceneGraph 具有高性能的开源3D图形工具包
  • Panda3D 用于3D渲染和游戏开发的框架,用Python和C++编写。
  • Skia 用于绘制文字,图形和图像的完整的2D图形库
  • urho3d 跨平台的渲染和游戏引擎。

图像处理

  • GIL:通用图像库
  • CImg :用于图像处理的小型开源C++工具包
  • CxImage :用于加载,保存,显示和转换的图像处理和转换库,可以处理的图片格式包括 BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K。
  • FreeImage :开源库,支持现在多媒体应用所需的通用图片格式和其他格式。
  • GDCM:Grassroots DICOM 库
  • ITK:跨平台的开源图像分析系统
  • Magick++:ImageMagick程序的C++接口
  • MagickWnd:ImageMagick程序的C++接口
  • OpenCV : 开源计算机视觉类库
  • tesseract-ocr:OCR引擎
  • VIGRA :用于图像分析通用C++计算机视觉库
  • VTK :用于3D计算机图形学,图像处理和可视化的开源免费软件系统。

国际化

  • gettext :GNU `gettext'
  • IBM ICU:提供Unicode 和全球化支持的C、C++ 和Java库
  • libiconv :用于不同字符编码之间的编码转换库

Jason

  • frozen : C/C++的Jason解析生成器
  • Jansson :进行编解码和处理Jason数据的C语言库
  • jbson :C++14中构建和迭代BSON data,和Json 文档的库
  • JeayeSON:非常健全的C++ JSON库,只包含头文件
  • JSON++ : C++ JSON 解析器
  • json-parser:用可移植的ANSI C编写的JSON解析器,占用内存非常少
  • json11 :一个迷你的C++11 JSON库
  • jute :非常简单的C++ JSON解析器
  • ibjson:C语言中的JSON解析和打印库,很容易和任何模型集成。
  • libjson:轻量级的JSON库
  • PicoJSON:C++中JSON解析序列化,只包含头文件
  • qt-json :用于JSON数据和 QVariant层次间的相互解析的简单类
  • QJson:将JSON数据映射到QVariant对象的基于Qt的库
  • RapidJSON: 用于C++的快速JSON 解析生成器,包含SAX和DOM两种风格的API
  • YAJL :C语言中快速流JSON解析库

日志

  • Log :设计非常模块化,并且具有扩展性
  • easyloggingpp:C++日志库,只包含单一的头文件。
  • Log4cpp :一系列C++类库,灵活添加日志到文件,系统日志,IDSA和其他地方。
  • templog:轻量级C++库,可以添加日志到你的C++应用程序中

机器学习

  • Caffe :快速的神经网络框架
  • CCV :以C语言为核心的现代计算机视觉库
  • mlpack :可扩展的C++机器学习库
  • OpenCV:开源计算机视觉库
  • Recommender:使用协同过滤进行产品推荐/建议的C语言库。
  • SHOGUN:Shogun 机器学习工具
  • sofia-ml :用于机器学习的快速增量算法套件

数学

  • Armadillo :高质量的C++线性代数库,速度和易用性做到了很好的平衡。语法和MatlAB很相似
  • blaze:高性能的C++数学库,用于密集和稀疏算法。
  • ceres-solver :来自谷歌的C++库,用于建模和解决大型复杂非线性最小平方问题。
  • CGal: 高效,可靠的集合算法集合
  • cml :用于游戏和图形的免费C++数学库
  • Eigen :高级C++模板头文件库,包括线性代数,矩阵,向量操作,数值解决和其他相关的算法。
  • GMTL:数学图形模板库是一组广泛实现基本图形的工具。
  • GMP:用于个高精度计算的C/C++库,处理有符号整数,有理数和浮点数。

多媒体

  • GStreamer :构建媒体处理组件图形的库
  • LIVE555 Streaming Media :使用开放标准协议(RTP/RTCP, RTSP, SIP) 的多媒体流库
  • libVLC :libVLC (VLC SDK)媒体框架
  • QtAv:基于Qt和FFmpeg的多媒体播放框架,能够帮助你轻而易举地编写出一个播放器
  • SDL :简单直控媒体层
  • SFML :快速,简单的多媒体库

网络

  • ACE:C++面向对象网络变成工具包
  • Asio:用于网络和底层I/O编程的跨平台的C++库
  • Casablanca:C++ REST SDK
  • cpp-netlib:高级网络编程的开源库集合
  • c:C语言的异步网络
  • libcurl :多协议文件传输库
  • Mongoose:非常轻量级的网络服务器
  • Muduo :用于Linux多线程服务器的C++非阻塞网络库
  • net_skeleton :C/C++的TCP 客户端/服务器库
  • c :基于C语言的超轻型软件平台,用于可扩展的服务器端和网络应用。 对于C编程人员,可以考虑node.js
  • Onion :C语言HTTP服务器库,其设计为轻量级,易使用。
  • POCO:用于构建网络和基于互联网应用程序的C++类库,可以运行在桌面,服务器,移动和嵌入式系统。
  • RakNet:为游戏开发人员提供的跨平台的开源C++网络引擎。
  • Tuf o :用于Qt之上的C++构建的异步Web框架。
  • WebSocket++ :基于C++/Boost Aiso的websocket 客户端/服务器库
  • ZeroMQ :高速,模块化的异步通信库

物理学

动力学仿真引擎

  • Box2D:2D的游戏物理引擎。
  • Bullet :3D的游戏物理引擎。
  • Chipmunk :快速,轻量级的2D游戏物理库
  • LiquidFun:2D的游戏物理引擎
  • ODE :开放动力学引擎-开源,高性能库,模拟刚体动力学。
  • fxBox2d:Box2D开源框架包装器。
  • Simbody :高性能C++多体动力学/物理库,模拟关节生物力学和机械系统,像车辆,机器人和人体骨骼。

机器人学

  • MOOS-IvP :一组开源C++模块,提供机器人平台的自主权,尤其是自主的海洋车辆。
  • MRPT:移动机器人编程工具包
  • PCL :点云库是一个独立的,大规模的开放项目,用于2D/3D图像和点云处理。
  • Robotics Library (RL): 一个独立的C++库,包括机器人动力学,运动规划和控制。
  • RobWork:一组C++库的集合,用于机器人系统的仿真和控制。
  • ROS :机器人操作系统,提供了一些库和工具帮助软件开发人员创建机器人应用程序。

科学计算

  • FFTW :用一维或者多维计算DFT的C语言库。
  • GSL:GNU科学库。

脚本

  • ChaiScript :用于C++的易于使用的嵌入式脚本语言。
  • Lua :用于配置文件和基本应用程序脚本的小型快速脚本引擎。
  • luacxx:用于创建Lua绑定的C++ 11 API
  • SWIG :一个可以让你的C++代码链接到JavaScript,Perl,PHP,Python,Tcl和Ruby的包装器/接口生成器
  • V7:嵌入式的JavaScript 引擎。
  • V8 :谷歌的快速JavaScript引擎,可以被嵌入到任何C++应用程序中。

序列化

  • Cap'n Proto :快速数据交换格式和RPC系统。
  • cereal :C++11 序列化库
  • FlatBuffers :内存高效的序列化库
  • MessagePack :C/C++的高效二进制序列化库,例如 JSON
  • protobuf :协议缓冲,谷歌的数据交换格式。
  • protobuf-c :C语言的协议缓冲实现
  • SimpleBinaryEncoding:用于低延迟应用程序的对二进制格式的应用程序信息的编码和解码。
  • Thrift :高效的跨语言IPC/RPC,用于C++,Java,Python,PHP,C#和其它多种语言中,最初由Twitter开发。

视频

  • libvpx :VP8/VP9编码解码SDK
  • FFmpeg :一个完整的,跨平台的解决方案,用于记录,转换视频和音频流。
  • libde265 :开放的h.265视频编解码器的实现。
  • OpenH264:开源H.364 编解码器。
  • Theora :免费开源的视频压缩格式。

虚拟机

  • CarpVM:C中有趣的VM,让我们一起来看看这个。
  • MicroPython :旨在实现单片机上Python3.x的实现
  • TinyVM:用纯粹的ANSI C编写的小型,快速,轻量级的虚拟机。

Web应用框架

  • Civetweb :提供易于使用,强大的,C/C++嵌入式Web服务器,带有可选的CGI,SSL和Lua支持。
  • CppCMS :免费高性能的Web开发框架(不是 CMS).
  • Crow :一个C++微型web框架(灵感来自于Python Flask)
  • Kore :使用C语言开发的用于web应用程序的超快速和灵活的web服务器/框架。
  • libOnion:轻量级的库,帮助你使用C编程语言创建web服务器。
  • QDjango:使用C++编写的,基于Qt库的web框架,试图效仿Django API,因此得此名。
  • Wt :开发Web应用的C++库。

XML

XML就是个垃圾,xml的解析很烦人,对于计算机它也是个灾难。这种糟糕的东西完全没有存在的理由了。-Linus Torvalds

  • Expat :用C语言编写的xml解析库
  • Libxml2 :Gnome的xml C解析器和工具包
  • libxml++ :C++的xml解析器
  • PugiXML :用于C++的,支持XPath的轻量级,简单快速的XML解析器。
  • RapidXml :试图创建最快速的XML解析器,同时保持易用性,可移植性和合理的W3C兼容性。
  • TinyXML :简单小型的C++XML解析器,可以很容易地集成到其它项目中。
  • TinyXML2:简单快速的C++CML解析器,可以很容易集成到其它项目中。
  • TinyXML++:TinyXML的一个全新的接口,使用了C++的许多许多优势,模板,异常和更好的异常处理。
  • Xerces-C++ :用可移植的C++的子集编写的XML验证解析器。

多项混杂

一些有用的库或者工具,但是不适合上面的分类,或者还没有分类。

  • C++ Format :C++的小型,安全和快速格式化库
  • casacore :从aips++ 派生的一系列C++核心库
  • cxx-prettyprint:用于C++容器的打印库
  • DynaPDF :易于使用的PDF生成库
  • gcc-poison :帮助开发人员禁止应用程序中的不安全的C/C++函数的简单的头文件。
  • googlemock:编写和使用C++模拟类的库
  • HTTP Parser :C的http请求/响应解析器
  • libcpuid :用于x86 CPU检测盒特征提取的小型C库
  • libevil :许可证管理器
  • libusb:允许移动访问USB设备的通用USB库
  • PCRE:正则表达式C库,灵感来自于Perl中正则表达式的功能。
  • Remote Call Framework :C++的进程间通信框架。
  • Scintilla :开源的代码编辑控件
  • Serial Communication Library :C++语言编写的跨平台,串口库。
  • SDS:C的简单动态字符串库
  • SLDR :超轻的DNS解析器
  • SLRE: 超轻的正则表达式库
  • Stage :移动机器人模拟器
  • VarTypes:C++/Qt4功能丰富,面向对象的管理变量的框架。
  • ZBar:'条形码扫描器'库,可以扫描照片,图片和视频流中的条形码,并返回结果。
  • CppVerbalExpressions :易于使用的C++正则表达式
  • QtVerbalExpressions:基于C++ VerbalExpressions 库的Qt库
  • PHP-CPP:使用C++来构建PHP扩展的库
  • Better String :C的另一个字符串库,功能更丰富,但是没有缓冲溢出问题,还包含了一个C++包装器。

软件

用于创建开发环境的软件

编译器

C/C++编译器列表

  • Clang :由苹果公司开发的
  • GCC:GNU编译器集合
  • Intel C++ Compiler :由英特尔公司开发
  • LLVM :模块化和可重用编译器和工具链技术的集合
  • Microsoft Visual C++ :MSVC,由微软公司开发
  • Open WatCom :Watcom,C,C++和Fortran交叉编译器和工具
  • TCC :轻量级的C语言编译器

在线编译器

在线C/C++编译器列表

  • codepad :在线编译器/解释器,一个简单的协作工具
  • CodeTwist:一个简单的在线编译器/解释器,你可以粘贴的C,C++或者Java代码,在线执行并查看结果
  • coliru :在线编译器/shell, 支持各种C++编译器
  • Compiler Explorer:交互式编译器,可以进行汇编输出
  • CompileOnline:Linux上在线编译和执行C++程序
  • Ideone :一个在线编译器和调试工具,允许你在线编译源代码并执行,支持60多种编程语言。

调试器

C/C++调试器列表

集成开发环境(IDE)

C/C++集成开发环境列表

  • AppCode :构建与JetBrains' IntelliJ IDEA 平台上的用于Objective-C,C,C++,Java和Java开发的集成开发环境
  • CLion:来自JetBrains的跨平台的C/C++的集成开发环境
  • Code::Blocks :免费C,C++和Fortran的集成开发环境
  • CodeLite :另一个跨平台的免费的C/C++集成开发环境
  • Dev-C++:可移植的C/C++/C++11集成开发环境
  • Eclipse CDT:基于Eclipse平台的功能齐全的C和C++集成开发环境
  • Geany :轻量级的快速,跨平台的集成开发环境。
  • IBM VisualAge :来自IBM的家庭计算机集成开发环境。
  • Irony-mode:由libclang驱动的用于Emacs的C/C++微模式
  • KDevelop:免费开源集成开发环境
  • Microsoft Visual Studio :来自微软的集成开发环境
  • NetBeans :主要用于Java开发的的集成开发环境,也支持其他语言,尤其是PHP,C/C++和HTML5。
  • Qt Creator:跨平台的C++,Javascript和QML集成开发环境,也是Qt SDK的一部分。
  • rtags:C/C++的客户端服务器索引,用于 跟基于clang的emacs的集成
  • Xcode :由苹果公司开发
  • YouCompleteMe:一个用于Vim的根据你敲的代码快速模糊搜索并进行代码补全的引擎。

构建系统

  • Bear :用于为clang工具生成编译数据库的工具
  • Biicode:基于文件的简单依赖管理器。
  • CMake :跨平台的免费开源软件用于管理软件使用独立编译的方法进行构建的过程。
  • CPM:基于CMake和Git的C++包管理器
  • FASTBuild:高性能,开源的构建系统,支持高度可扩展性的编译,缓冲和网络分布。
  • Ninja :专注于速度的小型构建系统
  • Scons :使用Python scipt 配置的软件构建工具
  • tundra :高性能的代码构建系统,甚至对于非常大型的软件项目,也能提供最好的增量构建次数。
  • tup:基于文件的构建系统,用于后台监控变化的文件。

静态代码分析

提高质量,减少瑕疵的代码分析工具列表

]]>
https://zuk.pw/index.php/2017/11/22.html/feed 0
smb/samba快速配置及配置参数详解 https://zuk.pw/index.php/2017/11/171.html https://zuk.pw/index.php/2017/11/171.html#respond Wed, 01 Nov 2017 05:51:00 +0000 https://zuk.pw/index.php/?p=171 回车–>&#……]]> 快速安装/配置

samba是Linux系统上的一种文件共享协议,可以实现Windows系统访问Linux系统上的共享资源,现在介绍一下如何在Ubuntu 16.04上安装和配置samba

安装软件

1. 更新源列表

打开”终端窗口”,输入sudo apt-get update–>回车–>”输入当前登录用户的管理员密码”–>回车,就可以了。

2. 安装samba

打开”终端窗口”,输入

sudo apt-get install samba samba-common

–>回车–>输入”y”–>回车–>安装完成。

配置

1. 新建共享目录并设置权限

  • 打开”终端窗口”,输入”sudo mkdir /home/files”–>回车–>共享目录share新建成功。

  • 输入”sudo chmod 777 /home/share”–>回车,这样用户就对共享目录有了写权限。

2. 打开配置文件smb.conf

打开”终端窗口”,输入”sudo gedit /etc/samba/smb.conf”–>回车–>打开了配置文件smb.conf。

  • #### Debugging/Accounting ####下面增加下面内容 ,大概在61行
   security = user
  • 在文件末尾增加下面的内容
[data]
  comment = server data
  path = /home/files
  browseable = yes
  writable = yes
# 增加下面配置则为公开访问,无需账号密码
  public=yes
  writable = yes
  create mask=0775
  directory mask=0775
  available = yes

3. 配置访问账号

添加用户(下面的hosea是我的用户名,之后会需要设置samba的密码)。

sudo smbpasswd -a hosea

参数详解

samba大约超过200个配置参数

[global]
  netbios name = HARDY   #设置服务器的netbios名字
  server string = my server #对samba服务器的描述
  workgroup = DEBIAN_FANS #samba服务器属于哪个工作组名或域名
  encrypt passwords = yes #密码需要加密
  message command = /bin/sh -c 'xedit %s ; rm %s' & #当winpopup向网络用户发消息时,此参数可用来接收消息,可惜没有发送。
  security = user     #用于登陆域,或用户验证登陆
  wins support = yes    #设置本地为wins服务器,当WINS SERVER没有启动,SAMBA利用广播来进行名字解析,
                     # 而WINS SERVER 是通过udp协议来进行包的传送和不同网络中的路由。 因此在不同的网络中进行NETbios解析,要打开wins server.
                      # samba 利用"remote browse sync" 来和远程的local master browser进行信息的同步 
  name resolve order = wins lmhosts hosts bcast # 解析netbios的顺序 (lmhosts-lan manager file)(hosts-unix的/etc/hosts,dns,nis)(wins)(bcast,广播) 
 ; wins server = 192.168.0.22 # 指定wins服务器的网络地址
 ; wins proxy = yes     # 如果指定的wins服务器在不同的网断,就需要打开
 ; dns proxy = yes      # 当wins服务器在wins中找不到名字的话,就会查找dns.很有用哦
 ; admin users = hardy   #samba的管理用户,默认是root.
  add user script = /usr/sbin/useradd -d /dev/null -g 100 -s /bin/false %u #代替手工的添加计算机账号(看pdc配置文件),我没有试成功。
  prefered master = yes  # 强制使samba成为local master
  local master = yes    # 使nmbd试着在子网中成为master browse(储存子网中所有的netbios name 所对应ip的列表)
  domain master = yes   # 使nmbd成为广域网的netbios name 所对应ip的列表,任务是同步所有子网中local master的列表。因此使各终端得到整个域的浏览列表,如果设置了`domain logons = yes`那么domain master默认是yes

  os level = 33   #[**操作系统**](http://lib.csdn.net/base/operatingsystem)级别,winNT4.0服务器-33 如果数值高于33,samba就成为local master browers不管网络中是否存在winNT4.0

                  # winNT3.51服务器-32
                  # winNT4.0客户机-17
                  # winNT3.51客户机-16
                  # win98 - 2
                  # win95 - 1
                  # win3.1- 1 

  time server = yes # nmbd将会告知windows的客户端自己是作为smb的时间服务器,可以用net time /yes /set 来同步时间
  domain logons = yes   #设置samba为win98/95所登陆的域服务器。 
  printer admin = hardy
  username map = /etc/samba/smbusers #用户别名文件。
  logon path =    # 看[profiles]的说明
  logon drive = Z:    # 把用户的home目录映射成z:盘,只适用于NT,但我用XP也可以
  logon home =  #指定客户端登陆的home目录的位置,当然[homes]目录需要定义哦,为了同时支持9x和nt登陆.该项要设置成为, 并且指定logon path =  
  socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192 #据说可以提高samba性能
  password server =    # 其他的NT 服务器,或samba服务器但security=server或domain 的ntbios 名字
  hosts allow = 192.168.0. #指定那些主机可以访问
  hosta deny = 192.168.8. #指定那些主机不可以访问
  interfaces = 192.168.0.100/255.255.255.0   #设置samba将对哪些网络接口进行服务。
  bind interface only = yes          # 如果设置成是,samba只对这几个网络接口服务
  socket address = 192.168.0.10        #强制samba只在该端口监听
  netbios aliases = yao xiao ping       # 设置3个samba虚拟服务器
  include = /etc/samba/smb.conf.another    #包括另外的samba配置文件
  show add printer wizard= yes  # 当用户添加打印机时,显示安装向导. 
  printcap name = /etc/printcap
  load printers = yes
  log file = /var/log/samba/%m.log       #日志文件
  max log size = 0               #日志文件的大小
  log level = 0                # 日志级别 0 表示没有,3 一般比较合理
  syslog = 2                  # syslog的日志级(0,err)(1,warning)(2,notice)(3,ifno)(4或以上,debug)
  syslog only = yes              #只使用系统日志,关闭samba日志
  smb passwd file = /etc/samba/smbpasswd
  unix password sync = yes           #当用户改变samba加密的密码时,SAMBA会试着更新UNIX用户密码
  passwd program = /usr/bin/passwd %u     #这个就指定更改密码的命令
  passwd chat = *New*password* %n\n *Retype*new*password* %n\n *passwd:*all*authentication*tokens*updated*successfully* #更改密码时的对话
  password level = "数字" 在win9x下密码最多出现大写字母的个数,因为9X是使用平文传送密码的。
  null password = yes   # 是否允许空密码
  pam password change = no #为samba打开pam改变密码控制机制的支持,
  obey pam restrictions = no #当encrypt passwords = yes 时,samba 会忽略pam的验证,因为pam不支持(挑战/回答)验证机制,他只用来做平文密码的验证。
  nt acl support = yes # 允许NT用户修改unix文件的属性
  announce as = NT     #告诉客户端,samba是以winNT的身份来运行的 
  announce version = 4.0  #告诉客户端,samba是以4.0版本来运行的
  remote announce = 192.168.33.33/DEBIAN_FANS #子网和工作组,允许SAMBA和子网同步浏览(local master) 
  browse list = yes    #samba将在服务器上生成浏览列表
  remote browse sync = 192.168.222.22 # samba 将会同步在其他子网(local master)的列表,但子网的(LOCAL MASTER)必须是SAMBA服务器
  unix realname #在客户端是否采用unix全文件名
  nis homedir = yes # SAMBA 采用NIS的/etc/nsswitch.conf 文件,而不用/etc/passwd,来找用户的home目录
  logon script = %U.bat #指定客户端登陆文件名
[netlogon]
  path = /home/samba/netlogon # 该目录中存放用户登陆脚本(logon script = %U.bat)
  writable = no
  guest ok = yes
  share modes = no    # 打开dos的锁全文件的方式,在比较繁忙的服务器上关闭它,会提高性能。
  ;write list = hardy,root # 指定哪些用户可以在该只读共享文件上有写的权限
[profiles]      # 设置每个登陆用户的环境,包括桌面的属性,开始菜单上应用程序,以及其他项目。它是储存在服务器的。
  path = /home/samba
  writable = yes  #允许些操作
  browsable = yes  #允许该目录被显示在系统资源中
  create mask = 0600
  directory mask = 0700
[printers]
  path = /var/spool/samba
  guest ok = yes
  browseable = yes
  printable = yes
  read only = yes
[cdrom]
  path = /mnt/cdrom
  read only = yes
  guest ok = yes
  locking = no   #由于是只读文件
  public = yes 
  preexec = /bin/mount /dev/cdrom  #在链接共享文件之前,要执行的命令
  postexec = /bin/umount /dev/cdrom #在断开共享文件之前,要执行的命令 但我不知道什么时候才算断开。
[homes]
  comment = Home
  magic script = hardy.sh #当用户打开该共享文件hardy.sh将被执行,结果将被重定向到客户端
  magic output = /var/log/magicoutput #指定结果输出到该文件
  volume = user-at-home # dos的盘符卷标
  read list = badguy  # 限制这些用户在可写文件上的些操作权限
  valid users = %S   # 可登陆用户
  invalid users = root  #不可登陆用户
  max connections = 0  # 最大连接数
  read only = no
  writable = yes
  create mode = 0777
  directory mode = 0775
  browseable = no
[public]
  path = /var/ftp
  dont descend = etc bin lib # 指定这些在/var/ftp目录下的目录是不可访问的。
  follow symlinks = yes   # 指定是否允许文件的链接
  wide links = yes      # 指定是否可以链接到/var/ftp以外的文件或目录
  hide dot files = yes      # 是否隐藏点文件
  hide files = /*.[**Java**](http://lib.csdn.net/base/javase)/*.cpp/ # 隐藏指定文件 
  veto files = /*config/*secret/ # 完全隐藏文件,比隐藏要强硬。重要文件使用
  delete veto files = no    # 当用户删除有veto files的目录时, 是否允许删除veto files以及目录.
  delete readonly = no     # 是否允许dos用户删除只读文件 
  security mask = 0777 # 0 表示允许修改,1 表示不允许
  create mask = 0777 # 如果上面的(security mask)没设,则按照这个模式
  force security mode = 0 # 当修改文件的属性,指定哪些模式必须设置
  force create mode = 0 # 如果上面的(force security mode)没设,则按照这个模式
  directory security mask = 0777 # 目录,同上.
  directory mask = 0777
  force directory security mode = 0777 
  force directory mode =0777
  case sensitive = no # 是否区分文件名的大小写(windows 是不区分的)
  default case = upper/lower  #设置默认的是大写还是小写
  preserve case = yes     #不进行大小写的转换,不转换成默认(default case)
  short preserve case = yes  #将文件名转成8.3的dos端文件名
  locking = yes      #由于文件只能同时被打开一次,当文件打开时,samba会自动让其他访问守候,为了文件不被破坏
  oplocks = no      #本地缓存,如果设置成yes,会提高samba的速度,据说在[**Linux**](http://lib.csdn.net/base/linux)-2.5以前的版本有bug,所以在2.4中还是设置成no
  level2 oplocks = no   # 同上

变量替换 VARIABLESUBSTITUTIONS

在配置文件中可以用很多字符串进行替换.例如,当用户以john的名称建立连接后,选项path = %u就被解释成path =/tmp/john

​    这些置换会在后面的描述中说明,这里说明一些可以用在任何地方的通用置换.它们是:
​    %U   对话用户名(客户端想要的用户名不一定与取得的一致.)
​    %G   %U的用户组名
​    %h   运行Samba的主机的internet主机名
​    %m   客户机的NetBIOS名(非常有用)
​    %L   服务器的NetBIOS名.这使得你可以根据调用的客户端来改变你的配置,这样你的服务器就可以拥有"双重个性".
​       Note that this parameter is not available when Samba listens on
​       port 445, as clients no longer send this information
​    %M   客户端的internet主机名
​    %R   协议协商后选择的协议,它可以是CORE,COREPLUS,LANMAN1,LANMAN2或NT1中的一种.
​    %d   当前samba服务器的进程号.
​    %a   远程主机的结构.现在只能认出来某些类型,并且不是100%可靠.目前支持的有Samba、WfWg、WinNT和Win95.任何其他的都被认作"UNKNOWN".如果出现错误就给samba-
​       发一个3级的日志以便修复这个bug.
​    %I   客户机的IP地址.
​    %T   当前的日期和时间.
​    %D   Name of the domain or workgroup of the current user.
​    %$(envvar)
​       The value of the environment variable envar.
​    The following substitutes apply only to some configuration options(only
​    those that are used when a connection has been established):
​    %S   当前服务名
​    %P   当前服务的根目录
​    %u   当前服务的用户名
​    %g   %u的用户组名
​    %H   %u所表示的用户的宿主目录
​    %N   tNIS服务器的名字.它从auto.map获得.如果没有用**--with-auto-**
​       **mount**选项编译samba,那么它的值和%L相同.
​    %p   用户宿主目录的路径.它由NIS的auot.map得到.NIS的auot.map入口项被分为"%N:%p".
​    灵活运用这些置换和其他的smb.conf选项可以做出非常有创造性的事情来.
]]>
https://zuk.pw/index.php/2017/11/171.html/feed 0
小米盒子刷原生安卓教程 https://zuk.pw/index.php/2017/10/89.html https://zuk.pw/index.php/2017/10/89.html#respond Sat, 21 Oct 2017 12:00:00 +0000 https://zuk.pw/?p=89 《小米盒子刷原生安卓教程》

小米盒子硬件配置好,价格偏低,无奈广告太多,特别是加了广告墙,操作性也变得很差。如果你也想把你手头的小米刷成原生安卓系统,那这边文章非常适合你,跟着我一步步来吧。

刷机前的准备

请确认你的盒子是否适合刷机,具体要求是,

  • 硬件:MDZ-18-AA, 也就是我们所说的小米盒子3增强版
  • 系统:通刷。目前最新的系统是1.5.33,只要不高于这个系统,都没有问题,高于这个系统的没法测试,无从得知。

磨刀不误砍柴时,刷机前把东西准备好,才不至于忙中出错,

  • 一个usb接口的鼠标
  • u盘一个,存放固件用

下载固件

下载原生安卓系统固件。目前有1.5.16、1.5.2两个版本的固件(链接: https://pan.baidu.com/s/1jJWdFF4 密码: mt7e),不要太在意这两个版本号,你可以随便挑一个刷,即使你现在的小米盒子系统是1.5.33也毫无问题。

把下载后的固件解压到U盘的根目录,目录结构为:/MDZ18AA_xxx(xxx为版本号,例如1.5.16,1.5.2, 下同) , 请一定要保证这个目录结构,否则刷机可能无法成功。

进入recovery模式,恢复出厂设置

首先,要解绑遥控器。用遥控器对准盒子,同时摁住‘home’和‘menu’键,这是电视会出现遥控器匹配电视盒子的画面,记住,这个时候已经解绑了遥控器,马上断开盒子电源即可,不要等到听到‘哔’的一声,那个时候就晚了,重来吧。

接下来进行恢复出厂设置的操作。遥控器对着盒子,同时摁住确认键和返回键,接通盒子电源,接下来会出现盒子双清的选择界面,选择清空所有数据,然后再选择恢复到出厂设置,重启。

安装 1_Settings_1.0.apk

插入U盘,进入/MDZ18AA_xxx/0_APPS目录,选择 1_Settings_1.0.apk, 按照提示一步步安装好后启动app,通过此app将系统改为英文。

安装 King Root app

/MDZ18AA_xxx/0_APPS在目录里找到2_KingRoot_4.8.0.apk,一步步安装好这个king root app后启动。由于app不支持遥控器操作,需要将usb接口鼠标插入电视盒子,用鼠标来操作app,按照app提示一步步root,完成后意味着盒子已经被root掉了。

安装SManager,并用SuperSU替换KingRoot

和上面一样,进入/MDZ18AA_xxx/0_APPS目录,找到3_SManager_3.0.4.apk,按照提示一步步安装完SManager。

启动app,点击‘Browse as root’按钮。随后,进入usb分区目录(/storage/usbotg/usbotg-sdaX,X为你的usb分区ID),SManager需要root权限,如果出现root权限对话框,同意即可。

复制整个MDZ18AA_xxx目录到storage/emulated/legacy。具体方法是,长摁MDZ18AA_xxx目录出现菜单,选择‘copy’。进入storage/emulated/legacy目录,选择‘Select this directory’,这样就开始复制了。

待复制完成后,MDZ18AA_xxx/1_ROOT目录,点击SuperSU.sh,以root权限运行脚本。运行后会出现模式选择对话框,请选择‘Expert Mode ’和‘binary updating mode’。运行完成后会要求重启,重启即可。

刷机,安装原生安卓系统

启动SManager,进入2_GAPPSTV目录,点击GappsTV.sh,以root权限运行脚本,刷机程序开始运行,刷机结束后会自动重启。

进入recovery模式,清除所有数据

用遥控器对准盒子,同时摁住‘home’和‘menu’键,解绑遥控器。断开电源后,用遥控器对着盒子,同时摁住确认键和返回键,再接通电源,进入recovery模式,进行数据清楚。

]]>
https://zuk.pw/index.php/2017/10/89.html/feed 0
阿里云服务器使用he-ipv6 https://zuk.pw/index.php/2017/04/169.html https://zuk.pw/index.php/2017/04/169.html#respond Mon, 24 Apr 2017 10:53:23 +0000 https://zuk.pw/index.php/?p=169 如果要求是FQDN地址,请登录到您的域名控制面板,设置一条AAAA记录到新设置的IPv6隧道地址。

在阿里云的将域名解析到IPv6地址,操作方法请参考:https://help.aliyun.com/knowledge_detail/6555875.html

  1. 请在 https://www.tunnelbroker.net 注册一个账号

  2. 登录到 tunnelbroker.net 后,请点击左侧导航的 Create Regular Tunnel ,输入您的IPv4地址,选择 HongKong 隧道服务器,来创建一个新的ipv6隧道配置

《阿里云服务器使用he-ipv6》

  1. 此例,创建好的ipv6隧道地址为:2001:470:18:401::2

《阿里云服务器使用he-ipv6》

  1. 然后,请点击 Example Configureations ,里边会给出在不同系统里可执行的命令,目的是创建ipv6隧道,如本例是Windows系统:

《阿里云服务器使用he-ipv6》

参考链接

he注册

ubuntu 配置he-ipv6

]]>
https://zuk.pw/index.php/2017/04/169.html/feed 0