利用 Jenkins 持续集成 Android 程序

Jenkins 是 Java 编写的开源持续集成(Continuous integration)工具 1。在上一篇推荐网站中提到的 AlternativeTo 中去搜索一下,能够看到很多持续集成的工具,像 GitHub 上经常看到的 Travis CI, 还有 Jenkins 的前身 Hudson。

安装

详情请见官网.

Linux 下:

wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

直接安装源中的 Package 有几点需要注意:

  1. Jenkins 会以守护进程(daemon)随机启动, 查看 /etc/init.d/jenkins
  2. 创建了 jenkins 用户来运行服务
  3. Log 文件 /var/log/jenkins/jenkins.log
  4. 配置地址 /etc/default/jenkins 比如 JENKINS_HOME 在该文件配置
  5. 默认 Jenkins 使用 8080 端口,启动 http://localhost:8080 开始配置 Jenkins 吧。

更多服务器 Apache , Nginx 的配置请见官网。

全局配置

这里默认已经有 Android 开发环境,也就是 JDK, Android-SDK,Gradle 都已经是完整的。进入 http://localhost:8080 配置,首次今日需要验证身份信息,验证之后创建用户,然后下载插件,进入之后,系统管理 -> 管理插件,需要安装以下插件:

  • Android Lint Plugin
  • Git plugin
  • Gradle plugin

如有其他插件 GitHub , gitlab 啦,可以就使用环境来选择安装。

更新玩插件,进入 系统管理 ->Global Tool Configuration , 然后配置 JDK 目录, Gradle 目录,Git 目录。当然需要知道当前自己机器上的绝对地址:

  • JDK: /usr/lib/jvm/java-7-openjdk-amd64
  • Gradle: /home/einverne/android-studio/gradle/gradle-2.10
  • Git: git

系统管理 -> 系统系统设置:

Environment variables 下添加:

键 : ANDROID_HOME 值:/home/einverne/Android/Sdk

如果这一行不添加,而 Android Studio 的工程没有在 local.properties 中指定 sdk.dir=/home/einverne/Android/Sdk 的话, Jenkins build failed, cannot found Android sdk2.

项目配置

配置好上面的环境,新建项目,名字 +”构建一个自由风格的软件项目”。 然后进入项目,配置

General

项目名字,项目描述, GitHub Project url。 如果想要自定义路径,可以在高级中设置。

源码管理

当然使用的是 Git, 然后是项目地址,然后需要验证身份信息,当然有很多的方式,用户名密码,用户名密钥,等等,根据自己的适用情况添加即可。可以选择分支 build.

构建触发器

这里可以选择何时触发构建, 有很多的方式,可以是有变动自动构建,也可以是定时构建,当然也有很多的触发方式。

构建环境

这边基本上在全局环境配置的时候就已经满足,细化一下 build 环境。

构建

这里需要选择 Invoke Gradle script, 然后在配置中选择刚刚在全局配置中配置的 Gradle 版本。

在 Tasks 下输入 clean build .

构建后操作

  1. 选择 Publish Android Lint results, 以便输出 Lint 结果,设置中输入 **/lint-results*.xml.
  2. 选择 Archive the artifacts 来存档 apk 文件,设置中输入 **/*.apk。 默认输出文件在 Workspace 下 app/build/outputs/apk/

遇到问题

Android Lint

Jenkins 默认启用 Lint 检查,所以需要在 build.gradleandroid 下添加

lintOptions {
    abortOnError false;
}

图文教程,Windows 下教程参考下面文章。

reference


2016-05-01 android , jenkins , gradle , ci

推荐网站之代替品:alternativeTo

总说“授人以鱼不如授人以渔”,寻找不同平台上的代替品,每次都会点进这个网站,或许是上一段时间内跨不同操作系统太频繁,所以导致寻求Mac下 Windows 某个软件的代替品的需求升高,现在渐渐的培养起自己只使用多平台客户端都存在的应用使用,而有些是在没有Linux下的应用,也尽量的能够找到功能相似的代替。所以 AlternativeTo 这个网站给我带来了很多的便利。

官网地址:http://alternativeto.net/

应用实例:

My Tracks

My Tracks 原本是Google推出Android上记录GPS轨迹的应用,在很早开始就一直使用,无奈Google宣布停止这款应用,而自身推出的 Fit 功能上也赶不上 My Tracks,想到这里真心感觉有点讽刺,几年后推出的产品在功能上竟然赶不上几年以前推出的应用。Google Photos 与 Picasa 也是。说偏了,回到 My Tracks, 直接访问 http://alternativeto.net/software/my-tracks/ 就能够找到很多的应用,上面有些用户也会给出功能的对比,有所少人喜欢某个应用,在几乎所有的情况下,排名第一的几乎就是最好用的了。

KMPlayer

有的时候多逛一逛这个网站能够有不少收获,就比如早之前我一直用的 KMPlayer , 而自某一个版本开始 KMPlayer 开始变得臃肿,收纳很多无用的功能之后,就可以到 KMPlayer 的 alternativeTo 来寻求代替品,最后会发现 PotPlayer 也非常好用,然后我一直使用至今。当然在 Linux 下就又可以跑到 PotPlayer 下面,然后找到 MPlayer 和 SMPlayer ,都非常不错,当然 VLC Media Player 也很棒。

当然还有很多很多的例子,都需要慢慢的发现,我曾经在上面找过 IDE 的代替品,找过编辑器的代替品,找过 SQLite Manager 的代替品,等等,他最好最方便的功能就是,当你在一个平台已经养成了一个使用习惯,突然间更换了一个平台,然后对这个环境很陌生,而在这个网站的指导下就能够迅速的找到代替品。快速的适应新的环境。而这样引出来的另一个问题就是,需要熟悉不同的工具。所以就回归到我之前所说,我几乎现在只考虑使用三个平台 Windows, Mac, Linux 下都存在产品的应用了。虽然现在像 Evernote,网易云音乐同样没有Linux客户端,但这已经是非常少的特例了。使用同样的应用,同样的环境才能提高效率,并且不同去适应不同的工具的差异。


2016-04-29 推荐网站 , website

每天学习一个命令:ps 显示当前运行进程

Linux 中的 ps 命令是 Process Status 的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。

简介

要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等等。总之大部分信息都是可以通过执行该命令得到的。

ps - report a snapshot of the current processes.

ps 提供的是执行时刻进程的状态,它提供的结果不是动态连续的;如果想对进程进行连续监控,应该用 top/htop 工具。

Linux 上进程有5种状态:

  1. 运行(正在运行或在运行队列中等待)
  2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
  3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
  4. 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
  5. 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)

ps工具标识进程的5种状态码:

D 不可中断 uninterruptible sleep (usually IO)
R 运行 runnable (on run queue)
S 中断 sleeping
T 停止 traced or stopped
Z 僵死 a defunct (”zombie”) process

语法

ps --help all

Usage:
 ps [options]

Basic options:
 -A, -e               all processes
 -a                   all with tty, except session leaders
  a                   all with tty, including other users
 -d                   all except session leaders
 -N, --deselect       negate selection
  r                   only running processes
  T                   all processes on this terminal
  x                   processes without controlling ttys

Selection by list:
 -C <command>         command name
 -G, --Group <gid>    real group id or name
 -g, --group <group>  session or effective group name
 -p, --pid <pid>      process id
     --ppid <pid>     select by parent process id
 -s, --sid <session>  session id
 -t, t, --tty <tty>   terminal
 -u, U, --user <uid>  effective user id or name
 -U, --User <uid>     real user id or name

  selection <arguments> take either:
    comma-separated list e.g. '-u root,nobody' or
    blank-separated list e.g. '-p 123 4567'

Output formats:
 -F                   extra full
 -f                   full-format, including command lines 
  f, --forest         ascii art process tree 显示进程间关系
 -H                   show process hierarchy 显示树形结构
 -j                   jobs format
  j                   BSD job control format
 -l                   long format
  l                   BSD long format
 -M, Z                add security data (for SE Linux)
 -O <format>          preloaded with default columns
  O <format>          as -O, with BSD personality
 -o, o, --format <format>
                      user defined format
  s                   signal format
  u                   user-oriented format
  v                   virtual memory format
  X                   register format
 -y                   do not show flags, show rrs vs. addr (used with -l)
     --context        display security context (for SE Linux)
     --headers        repeat header lines, one per page
     --no-headers     do not print header at all
     --cols, --columns, --width <num>
                      set screen width
     --rows, --lines <num>
                      set screen height

Show threads:
  H                   as if they where processes
 -L                   possibly with LWP and NLWP columns
 -m, m                after processes
 -T                   possibly with SPID column

Miscellaneous options:
 -c                   show scheduling class with -l option
  c                   show true command name 显示进程真实名称
  e                   show the environment after command
  k,    --sort        specify sort order as: [+|-]key[,[+|-]key[,...]]
  L                   list format specifiers
  n                   display numeric uid and wchan
  S,    --cumulative  include some dead child process data
 -y                   do not show flags, show rss (only with -l)
 -V, V, --version     display version information and exit
 -w, w                unlimited output width

        --help <simple|list|output|threads|misc|all>
                      display help and exit

For more details see ps(1).

基本使用

打印所有用户的运行进程

ps aux
  • a 显示所有用户的进程
  • u 显示进程的所有者
  • x 显示非终端启用的进程

输出:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  10656   668 ?        Ss   Apr12   1:14 init [2]
root         2  0.0  0.0      0     0 ?        S    Apr12   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    Apr12   4:28 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S    Apr12   0:00 [kworker/u:0]

说明:

  • USER:该 process 属于那个使用者账号的
  • PID :该 process 的号码
  • %CPU:该 process 使用掉的 CPU 资源百分比
  • %MEM:该 process 所占用的物理内存百分比
  • VSZ :该 process 使用掉的虚拟内存量 (Kbytes)
  • RSS :该 process 占用的固定的内存量 (Kbytes)
  • TTY :该 process 是在那个终端机上面运作,若与终端机无关,则显示 ?,另外, tty1-tty6 是本机上面的登入者程序,若为 pts/0 等等的,则表示为由网络连接进主机的程序。
  • STAT:该程序目前的状态,主要的状态有
  • R :该程序目前正在运作,或者是可被运作
  • S :该程序目前正在睡眠当中 (可说是 idle 状态),但可被某些讯号 (signal) 唤醒。
  • T :该程序目前正在侦测或者是停止了
  • Z :该程序应该已经终止,但是其父程序却无法正常的终止他,造成 zombie (疆尸) 程序的状态
  • START:该 process 被触发启动的时间
  • TIME :该 process 实际使用 CPU 运作的时间
  • COMMAND:该程序的实际指令

显示所有进程信息

ps -A

输出:

  PID TTY          TIME CMD
    1 ?        00:01:20 systemd
    2 ?        00:00:00 kthreadd
    3 ?        00:00:13 ksoftirqd/0
    5 ?        00:00:00 kworker/0:0H
    7 ?        00:17:02 rcu_sched
    8 ?        00:00:00 rcu_bh
    9 ?        00:00:03 migration/0
   10 ?        00:00:02 watchdog/0

显示指定用户所有进程

ps a -u root

显示所有进程信息,连同命令行

 ps -ef
 ps aux

ps 与grep 常用组合用法,查找特定进程

ps -ef | grep ssh

输出:

ps -ef | grep ssh
root     18928 22845  0 21:10 ?        00:00:00 sshd: root@pts/4
root     19852 20288  0 21:25 pts/2    00:00:00 grep ssh
root     22845     1  0 Jun18 ?        00:00:32 /usr/sbin/sshd

将目前属于您自己这次登入的 PID 与相关信息列示出来

ps -l

输出:

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0 17398 17394  0  75   0 - 16543 wait   pts/0    00:00:00 bash
4 R     0 17469 17398  0  77   0 - 15877 -      pts/0    00:00:00 ps

各相关信息的意义:

  • F 代表这个程序的旗标 (flag), 4 代表使用者为 super user
  • S 代表这个程序的状态 (STAT),关于各 STAT 的意义将在内文介绍
  • UID 程序被该 UID 所拥有
  • PID 就是这个程序的 ID !
  • PPID 则是其上级父程序的ID
  • C CPU 使用的资源百分比
  • PRI 这个是 Priority (优先执行序) 的缩写,详细后面介绍
  • NI 这个是 Nice 值,在下一小节我们会持续介绍
  • ADDR 这个是 kernel function,指出该程序在内存的那个部分。如果是个 running的程序,一般就是 “-“
  • SZ 使用掉的内存大小
  • WCHAN 目前这个程序是否正在运作当中,若为 - 表示正在运作
  • TTY 登入者的终端机位置
  • TIME 使用掉的 CPU 时间。
  • CMD 所下达的指令为何

在预设的情况下, ps 仅会列出与目前所在的 bash shell 有关的 PID 而已,所以,当使用 ps -l 的时候,只有三个 PID。

列出类似程序树的程序显示

ps -axjf

输出:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
    2     3     0     0 ?           -1 S        0   4:28  \_ [ksoftirqd/0]
    2     5     0     0 ?           -1 S        0   0:00  \_ [kworker/u:0]
    2     6     0     0 ?           -1 S        0   0:00  \_ [migration/0]
    1 20287 20287 20287 ?           -1 Ss       0   0:01 SCREEN -S lnmp
20287 20288 20288 20288 pts/2    19855 Ss       0   0:00  \_ /bin/bash
20288 19855 19855 20288 pts/2    19855 R+       0   0:00      \_ ps -axjf

找出与 cron 与 syslog 这两个服务有关的 PID 号码

ps aux | grep '(cron|syslog)'

输出:

root      2682  0.0  0.0  83384  2000 ?        Sl   Nov02   0:00 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
root      2735  0.0  0.0  74812  1140 ?        Ss   Nov02   0:00 crond
root     17475  0.0  0.0  61180   832 pts/0    S+   16:27   0:00 egrep (cron|syslog)

输出指定的字段

ps -o pid,ppid,pgrp,session,tpgid,comm

  PID  PPID  PGRP  SESS TPGID COMMAND
17398 17394 17398 17398 17478 bash
17478 17398 17478 17398 17478 ps

外延

ps aux | less
ps aux > /tmp/ps.txt

2016-04-25 ps , command , linux , process

should I git ignore .project file under eclipse

Recently, I have worked on a C++ project create by eclipse using CDT. And I generate my .gitignore file at gitignore.io. However when I shared my project to Git, and want to import my project on other computer. I find I cannot import my Exist project into Eclipe workspace.

After I did search, I notice that my gitignore file just ignore .project file which has an annotation says that it’s Eclipse Core. I found that each time Eclipse want to import an exist project. Eclipse will try to find this file. The eclipse documentation states the porpuse of .project file as follow:

The purpose of this file is to make the project self-describing, so that a project that is zipped up or released to a server can be correctly recreated in another workspace.

and

If a new project is created at a location that contains an existing project description file, the contents of that description file will be honoured as the project description. One exception is that the project name in the file will be ignored if it does not match the name of the project being created. If the description file on disk is invalid, the project creation will fail.

So I decide to not ignore .project in git version control. And remove the .project ignore in .gitignore file. After that it is easy for me to import project into Eclipse.

I followed @lanoxx’s idea to keep .project file under git version control. So after you cloned your repository on other place, you can simply use Import -> Existing Project from Workspace. Eclipse will take care the .project file and recreate other project related config files for you, like .cproject under C++ project, and .classpath or .settings/ under java environment.

If you do not share the .project file, then it is not possible to import the project with Eclipse. You will need to create a new project with the project wizard first, and then you can choose import “General->File System”, this will copy all the files into your workspace. This is probably not what you want, because it means that you cannot clone the git repository into the workspace, you must clone it somewhere else and then import it from there. Therefore you should always share the .project file.

About all, I talk about the .project file. Following I have done a little search for the .cproject. This file contain all the settings provided for the particular selected Toolchain. For example, if the project needs to be created with gcc, then this .cproject file will contain all the compiler, linker options used by gcc. This file is also important to reimport the project. All your settings in project properties will remain if you choose to keep this file under track.

reference


2016-04-23 eclipse , C++ , CDT , git , gitignore

btsync 体验

最近在安装 Resilio Sync 的时候发现,竟然被屏蔽了,官网被屏蔽了竟然连 key 都下载不了,可以使用之前写过的 proxychains 代理 来使用代理下载这个 key。

更新

惊闻 btsync 已经改名字,现在叫 Resilio Sync ,官网地址也改为: https://www.resilio.com/

可以从 这里 获取不同平台客户端。

Linux 安装 Package 可以参考 https://help.getsync.com/hc/en-us/articles/206178924 这里

创建文件 /etc/apt/sources.list.d/resilio-sync.list, 添加如下内容:

deb http://linux-packages.resilio.com/resilio-sync/deb resilio-sync non-free

添加公钥:

wget -qO - https://linux-packages.resilio.com/resilio-sync/key.asc | sudo apt-key add -

安装:

sudo apt-get update
sudo apt-get install resilio-sync

配置文件存储地址 https://help.getsync.com/hc/en-us/articles/206664690

Linux 下配置文件地址: /var/lib/resilio-sync

啊,安装好了之后,添加这个 key,当个示例啦 BB63I5PBPBFDELAPXI6NTF47IPNZQAAJZ ,一周一本好书。

如果想要手动开启或者关闭 Resilio Sync 可以使用如下命令:

sudo service resilio-sync stop
sudo service resilio-sync start

原文

全称 BitTorrent Sync , 我习惯了叫他 btsync 了。想要了解他的前世今生直接去看维基百科就好了。一句话概括,他就是一个同步工具,类Dropbox,但是利用 P2P等等 bt 种子的技术。当然私人使用当成网盘工具也好,当成分享工具也好,看个人使用了。不过黑客提醒,虽然是去中心化的,但是安全性依然存在问题,最好不要传输私人信息。

官网地址: https://www.getsync.com/

全平台

现在使用任何一个工具或者服务,我首要考虑的问题离不开跨平台了,最好是Windows , Linux, Mac 下全部都有,不然在平台间来回切换不同的服务和工具时间成本,学习成本太高了。也正是因为这个原因我放弃了 Google Drive 而转用 Dropbox,作为主力同步工具。当然 btsync 在全平台都有客户端,甚至连一些 NAS,路由器设备都有。

安装

安装非常简单,去官网下载,下一步下一步,OK。当然 Linux 下,如果不想使用 下一步下一步安装法,也可以使用命令从 PPA 里拖。

PPA

sudo add-apt-repository ppa:tuxpoldo/btsync
sudo apt-get update

For normal desktop use, you only need to install btsync-user:

sudo apt-get install btsync-user

Alternatively, if you’re setting up your BTSync server, install btsync:

sudo apt-get install btsync

btsync client

在官网根据自己的机器选择合适的 client 下载并解压。并运行:

./btsync

即可。

默认的Web GUI地址是 : http://127.0.0.1:8888

更加详细的安装指南可以参考这篇

VPS上架设

类似 Linux 下安装,官网下载并解压 btsync 文件。

tar -zxvf BitTorrent-Sync_x64.tar.gz

然后执行:

./btsync --dump-sample-config > btsync.conf

创建配置文件,然后修改 btsync.conf 配置文件中的:

"listen" : "0.0.0.0:8888" 

还有 loginpassword , 端口默认是8888,可修改成其他没有冲突的。loginpassword 是登陆用户名和密码。其他配置看注释修改即可。参考官网 config 文章.

然后保存配置文件,启动:

./btsync --config btsync.conf

在浏览器中就能够在 http://ip:port/ 访问 Web GUI。

然后在本地获取同步 key ,和 VPS 上同步即可。

技巧

移动同步后的文件夹

如果你已经同步了一个文件夹,比如在 ~/books,现在想要将该同步的目录移动到 ~/btsync/books 目录下。 就像Dropbox 同步已经存在的文件夹一样,如果单纯的再重新下载一边太麻烦了。所以幸好 btsync 和 dropbox 都有这样的性质,同步的内容都有文件记录,将文件重新加入索引,等索引完之后就可以继续和其他的文件同步了。

  1. 拷贝该文件夹的”共享秘钥”
  2. 从 btsync 中移除该文件夹
  3. 在本地硬盘移动文件夹到新的位置
  4. 重新在 btsync 用之前的”共享秘钥“,添加该文件夹

VPS 上启用 https

默认 btsync 的 web gui 是没有启用加密的,如果想要使用 https://ip:port/gui 来访问,则需要使用 config 配置,并在config 配置中设置 force_https, ssl_certificate,ssl_private_key ,然后重启 btsync 。

如果觉得这样让 btsync 直接获取证书不安全,这里 还有另外一种配置,利用 nginx 的代理。

分享密钥的网站

推荐几个常用 KEY

  • 神key BCWHZRSLANR64CGPTXRE54ENNSIUE5SMO
  • 最新电影 BA6RXJ7YOAOOFV42V6HD56XH4QVIBL2P6
  • 经济学人 BYRRPM52YK6Z6TETDQITFXBV647XLCNIO
  • Kindle 中文伴侣精品 BOC3NIGPF2DOKETOF2FAHXJXE2HF24QWC
  • 每周更新图书 BB63I5PBPBFDELAPXI6NTF47IPNZQAAJZ

reference


2016-04-18 btsync , 产品体验

小行星视图App review

最近迷上了360度全景,搞了得图800,和理光 theta m15的全景相机玩。然后就对周边的全景处理App都体验了一下。最早接触到 Sphere Photo 也要归功于 Google 的原生 Camera, 然而因为不知道的原因,在 Android kitkat 之后的版本中这个小行星视图就消失不见了。而我还是依然很怀念这样的视图。下面就是一些 Play Store 中存在的制作小行星视图的App。

Android Apps

Tiny Planet FX Pro

完整却不够完美 市场上唯一一款收费的小行星app,但是给我的感觉却是做的不够精致和完美,今天竟然处理出不完整的人脸。处理图像甚至比不上另一款免费的app。

Little Planet

除了开始的广告一切还好 开始的广告可能是让很多人打低分的原因,但是这款app,确实达到了我的需求,并且实现的很好。开发者可以尝试提供pro版本来去除广告或者内购去广告。

Tiny Planet - Globe Photo

广告多功能简单 太多影响操作的广告,横幅广告侵占了操作预览区域。功能比不上其他app。

Spherify

功能简单广告影响使用 功能几乎没有,处理时间太长。广告占据太多篇幅。

最后推荐 Little Planet , 虽然在App开始出现了全屏广告,但是效果及功能和收费的 Tiny Planet FX Pro 相差不大。

temple

android

cosoc

How to make sphere photo using photoshop

大多数时候我没有时间用 Google Camera 照完整个全景,这个时候如果可以后期合成当然是最好的,于是就有了这样一篇文章 ,只要有一张全景照片,利用 Photoshop 同样可以实现 Sphere Photo。 同样也可以参考这篇文章

最后推荐一个社区 https://plus.google.com/u/0/communities/115970110085205516914 ,社群的简介里面有很多教程,并且分享的 Post,质量都很高。


2016-04-16 Android , SpherePhoto , Android app

Python 笔记

多重继承

在 Python 中如果一个类继承自多个类,这种行为被称为多重继承 multiple inheritance,虽然多重继承非常有用,但是需要注意一些问题,否则会出现不可预见的问题。

在使用多重继承时,如果一个方法从多个超类中继承,先继承的类中的方法会重写后继承类中的方法。(超类顺序为定义 class 时的顺序)。

静态方法和类成员方法

Python 2.4 中,引入了装饰器(decorators) 的语法,能够对任何可调用的对象进行包装,既能够用于方法也能够用于函数。使用 @ 操作符,在方法或函数上将装饰器列出,指定一个或者多个装饰器。多个装饰器在应用时的顺序与指定顺序相反。

class Date(object):

    def __init__(self, day=0, month=0, year=0):
        self.day = day
        self.month = month
        self.year = year

    @classmethod
    def from_string(cls, date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        date1 = cls(day, month, year)
        return date1

    @staticmethod
    def is_date_valid(date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        return day <= 31 and month <= 12 and year <= 3999

date2 = Date.from_string('11-09-2012')
is_date = Date.is_date_valid('11-09-2012')

classmethod 必须有一个指向 class object 的 reference 作为第一参数,而 staticmethod 则不需要。

Class Method

C++ 有重载的功能,但是 Python 缺乏重载的机制,所以就有了 classmethod,可以想象成另外一个构造函数

@classmethod
def from_string(cls, date_as_string):
    day, month, year = map(int, date_as_string.split('-'))
    date1 = cls(day, month, year)
    return date1

date2 = Date.from_string('11-09-2012')

cls 是一个持有 class self 的对象,但是不是 class 的一个实例。如果继承了 Date 类,所有的子类都会拥有 from_string 方法。

Static method

对于这个例子,is_date_valid 方法不需要关心类内部的其他变量和方法,但是这个 valid 方法和 Date 相关,可以定义为静态方法。和其他语言中的静态方法可以一起理解。

getattr setattr

拦截 intercept 对象的所有特性访问是可能的,然后有一些魔法方法。比如 __getattr___setattr__

  • __getattribute__(self.name) 当特性 name 被访问时自动被调用,只能在新式类中使用
  • __getattr__(self.name) 当特性 name 被访问且对象没有相应的特性时被自动调用
  • __setattr__(self.name.value) 当试图给特性 name 赋值时被自动调用
  • __delattr__(self.name) 当试图删除特性 name 时被自动调用

这里是一些区别

  • __getattribute__ 无条件被调用,任何对象的属性访问时都会隐式调用,比如 t.__dict__ 其实是执行了 t.__getattribute__("__dict__") ,所以如果我们在重载__getattribute__中又调用__dict__的话,会无限递归,用 object 来避免,即 object.getattribute(self, name)
  • __getattr__ 只有 __getattribute__ 找不到的时候才会调用 __getattr__

举例

class Attr(object):

    def __init__(self, name):
        self.name = name

    def __getattribute__(self, item):
        print("__getattribute__ " + item)
        return object.__getattribute__(self, item)

    def __getattr__(self, item):
        print("__getattr__ " + item)

    def __setattr__(self, key, value):
        print("__setattr__ key %s, value %s" % (key, value))
        object.__setattr__(self, key, value)


if __name__ == '__main__':
    attr = Attr('wendy')
    print("main " + attr.name)
    attr.name = 'nancy'

在这个例子中,输出结果

__setattr__ key name, value wendy
__getattribute__ name
main wendy
__setattr__ key name, value nancy

迭代器

在 Python 中,很多对象都是可以通过 for 语句来直接遍历的,例如 list、string、dict 等等,这些对象都可以被称为可迭代对象。迭代器对象要求支持迭代器协议的对象,在 Python 中,支持迭代器协议就是实现对象的__iter__()next() 方法。其中__iter__() 方法返回迭代器对象本身;next() 方法返回容器的下一个元素,在结尾时引发 StopIteration 异常。

class PowTwo:
    """Class to implement an iterator
    of powers of two"""

    def __init__(self, max=0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration


p = PowTwo(5)
for i in p:
    print(i)

生成器


2016-04-04 python , class , inheritance

Java 查漏补缺之 Thread 类中 interrupt() interrupted() isInterrupted() 区别

Thread 类中有三个方法长得非常像,也特别容易混淆,但是使用起来却非常不同:

public void interrupt() // 无返回值
public boolean isInterrupted() // 有返回值
public static boolean interrupted() // 静态,有返回值

解释

  • interrupt(): 中断本线程

      myThread.interrupt();// 中断的是调用 interrupt() 方法的线程
    

    阻塞于 wait/join/sleep 的线程,中断状态会被清除掉,同时收到异常 InterruptedException;而其他情况中断状态都被设置,并不一定收到异常。interrupt() 方法其实是通知线程该中断了。线程具体中断还是继续执行,应该由被执行线程自己处理。

    具体来说,当一个线程调用 interrupt() 方法时:

      - 线程处于阻塞状态(sleep,wait,join 等),线程立即退出被阻塞状态,抛出 InterruptedException 异常
      - 线程处于正常活动状态,会将线程中断标志设置为 true,被设置中断标志的线程将继续正常运行
    

    一个线程如果有被中断的需求,在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程

      Thread thread = new Thread(() -> {
          // 若未发生中断,就正常执行任务
          while (!Thread.interrupted()) {
              // 正常任务代码
          }
          // 中断处理代码
          doSomething();
      });
      thread.start();
    
      // 一段时间以后
      thread.interrupt();
    
  • isInterrupted(): 检测本线程是否已经中断

      myThread.isInterrupted();// 判断本线程 myThread 是否中断
    

    如果已经中断,则返回 true,否则 false。中断状态不受该方法的影响。 如果中断调用时线程已经不处于活动状态,则返回 false。

  • interrupted(): 检测当前线程是否已经中断

      Thread.interrupted();// 判断该语句所在线程是否中断
    

    如果已经中断,则返回 true,否则 false,并清除中断状态。换言之,如果该方法被连续调用两次,第二次必将返回 false,除非在第一次与第二次的瞬间线程再次被中断。如果中断调用时线程已经不处于活动状态,则返回 false。

横向对比

后两个方法的区别横向比较:

isInterrupted() interrupted()
实例方法 类方法
判断本线程 判断当前线程
仅读取中断状态 读取并清除中断状态

reference


2016-04-02 java , thread , interrupt

每天学习一个命令:fdisk 查看磁盘详情

Fdisk命令用于观察硬盘实体使用情况,可以用来列出机器中所有磁盘的个数,也能列出所有磁盘分区情况,也可对硬盘分区(适用于2T以下磁盘,高于2T磁盘使用 parted)。

常见用法

显示所有磁盘的分区详情

fdisk -l

常见的磁盘标示都是 sda, sdb 类似,而分区则是在磁盘标示后面添加数字,比如 sda1, sda2, … , sdb3 等等。

选择进行操作的磁盘

fdisk /dev/sdb

2016-04-02 fdisk , disk , linux , partition , command

查看当前正在使用哪种 Shell

当前正在运行的 shell 路径被保存在 $0 环境变量中,可以使用如下方式查看

echo $0

根据不同系统的实现,输出可能会是当前正在运行的 shell,或者是当前运行的 shell 的路径。

prompt:~$ echo $0
/bin/bash
prompt:~$ sh
sh-4.0$ echo $0
sh
sh-4.0$ exit
exit
prompt:~$ /bin/sh
sh-4.0$ echo $0
/bin/sh
sh-4.0$

$SHELL 变量保存了用户偏好的 shell,而不是当前正在运行的 shell。

更多关于 shell 的默认特殊变量,可以查看之前的总结


2016-03-27 linux , shell , bash , sh , zsh

电子书

Google+

最近文章

  • 修正关于 HTTP Header 的错误认识 HTTP 请求的 Header 是不区分大小写的!,一直以为 HTTP 请求的请求头是有区分大小的,知道今天调试发现 Spring 将 header 全部处理成小写,然后有人提了 Bug 58464 然后看到 Stackoverflow 上面有人回答。
  • 解决 failed to create bus connection no such file or directory 错误 今天在修改 hostname 使用 sudo hostnamectl set-hostname ds 命令时遇到问题:
  • Vim 的颜色主题 Retro groove color scheme for Vim
  • Linux Mint 下禁用 Alt 拖拽窗口 问题的出现,Linux Mint 使用了很长时间了,一直也没有啥大的问题,只是最近自定义一些快捷键,Alt + Shift ,发现所有的 Alt 相关的操作,只要按住 Alt 键,然后鼠标在任何窗口中就变成了小手,拖拽会直接拖动窗口。
  • 威联通折腾篇八:重启服务 家里遇到一次断电,然后 NAS 就这样异常关机了,重启之后提示磁盘有些碎片需要整理,整理的时候 Qnap 会停止 NAS 上所有的服务,包括 Container Station 中的内容,而 Qnap 说了会在检查完磁盘之后重新启动的,然而并没有,所以只能手动来重启这些服务。