Fedora 23 Workstation

Fedora 23 Workstation

自从半年多前硬盘因为分区出现一些小问题,重新分区后一直没有恢复 Fedora 系统分区。 一直等着 Fedora 23 发布,刚好不久前发布了,就新装一个,继续和 Arch Linux 及 Windows 10 一起为我服务,哈哈~

由于现在 Linux 发行版的更新迭代都是非常快的,于是就不考虑刻录光盘了。 由于硬盘分区表还是使用 MBR ,使用 GRUB for DOS 依然可以正常引导各个系统,相安无事。

这边使用了一个 8GB 的 U 盘( FAT32 系统分区格式)安装了 GRUB for DOS ,可以引导各个系统及其 LiveCD 等,已经成为我安装系统的主要工具了(比如在新机器上新装 Arch Linux/Linux Mint 等也使用它了)。

新的 Fedora 23 Workstation iso 文件需要类似这样的 GRUB for DOS 菜单设置:

title Fedora 23 Workstation
root (hd0,0)
kernel (hd0,0)/fedora23/isolinux/vmlinuz0 root=live:LABEL=Fedora-Live-WS-x86_64-23-10 rootfstype=auto ro rd.live.image rhgb rd.luks=0 rd.md=0 rd.dm=0 iso-scan/filename='/fedora23/Fedora-Live-Workstation-x86_64-23-10.iso'
initrd (hd0,0)/fedora23/isolinux/initrd0.img

其中,我把 Fedora-Live-Workstation-x86_64-23-10.iso 以及从其中解压缩出来的 isolinux/ 文件夹一起放在了 U 盘第一个分区的 fedora23/ 文件夹下了。

使用这个 U 盘的这个 GRUB of DOS 菜单引导 Feodra 23 Workstation LiveCD 成功安装 Fedora 23 Workstation 。

如果不想将 GRUB 2 安装到硬盘上的话,需要在选择分区的时候取消安装引导程序, 安装成功之后,再将用于 Fedora 23 Workstation 系统引导的 GRUB for DOS 菜单添加到 GRUB for DOS 的菜单配置文件中,比如我目前的(包括了 Arch Linux 及 Fedora 23 Workstation 以及回到 Windows 引导菜单等):

color blue/green yellow/red white/magenta white/magenta
timeout 10
default /default

title Arch Linux
kernel (hd0,7)/boot/vmlinuz-linux root=/dev/sda8 rw
initrd (hd0,7)/boot/initramfs-linux.img
boot

title Fedora
kernel (hd0,9)/vmlinuz root=/dev/sda10 rw
initrd (hd0,9)/initramfs.img
boot

title find and load BOOTMGR of Windows VISTA
fallback 2
find --set-root --ignore-floppies /bootmgr
chainloader /bootmgr
savedefault --wait=2

title back to dos
quit

title reboot
reboot

title halt
halt

需要注意的是, Fedora 不会像 Arch Linux 那样将当前使用的 Linux kernel 的系统引导文件 vmlinuz-linux 和 initramfs-linux.img 固定放在一个位置,比如 /boot 文件夹下,所以我手动做了几个软链接,让 /vmlinuz 和 /initramfs.img 分别指向当前使用的 Linux kernel 的系统引导文件。每次更新完 Linux kernel 时候需要更新这几个软链接。

依稀记得 Ubuntu/Debian 好像默认是类似这样做的。。。

其中 Fedora 23 Workstation iso 文件的 GRUB for DOS 菜单设置主要是参考了 GRUB 2 的:

http://bbs.wuyou.net/forum.php?mod=redirect&goto=findpost&ptid=372875&pid=3158966

附:我 U 盘中当前使用的其他的一些发行版的 GRUB for DOS 引导菜单:

title Fedora 20 Xfce LiveCD
root (hd0,0)
kernel (hd0,0)/fedora/isolinux/vmlinuz0 root=live:/dev/sda1:/fedora/ rootfstype=auto ro rd.live.image quiet
initrd (hd0,0)/fedora/isolinux/initrd0.img

title CentOS 7.1.1503 LiveCD
root (hd0,0)
kernel (hd0,0)/centos/isolinux/vmlinuz0 root=live:/dev/sda1:/centos/ rootfstype=auto ro rd.live.image quiet
initrd (hd0,0)/centos/isolinux/initrd0.img

title Ubuntu 12.04.5 desktop LiveCD
root (hd0,0)
kernel (hd0,0)/ubuntu/vmlinuz.efi boot=casper iso-scan/filename=/ubuntu/ubuntu-12.04.5-desktop-amd64.iso locale=zh.CN.UTF-8
initrd (hd0,0)/ubuntu/initrd.lz

title linuxmint-17.2-cinnamon-64bit  desktop LiveCD
root (hd0,0)
kernel (hd0,0)/mint/vmlinuz boot=casper iso-scan/filename=/mint/linuxmint-17.2-cinnamon-64bit.iso
initrd (hd0,0)/mint/initrd.lz

title Arch Linux 2015,05,01
find --set-root /archlinux-2015.05.01-dual.iso
map /archlinux-2015.05.01-dual.iso (0xff) || map --mem --heads=0 --sectors-per-track=0 /archlinux-2015.05.01-dual.iso (0xff)
map --hook
chainloader (0xff)
boot

Python: 别在迭代容器 list/dict 时候增减容器内的元素

别在迭代容器 list/dict 时候增减容器内的元素:

Python 3.5.0
>>> aa = [1, 2, 3, 4, 5, 6]
>>> for a in aa:
>>>     if 2 < a < 5:
>>>         aa.remove(a)
>>> aa
[1, 2, 4, 5, 6]

反面参考来源:

http://www.oschina.net/translate/playing-around-with-await-async-in-python-3-5

http://benno.id.au/blog/2015/05/25/await1

使用 RubyInstaller for windows 遇到的 RubyGems 源的 SSL 证书问题

使用 RubyInstaller for windows 遇到的 RubyGems 源的 SSL 证书问题

2015,10,24

问题

如果不安装证书的话,

在 MSYS2 中,RubyGems 源无论是使用 https://ruby.taobao.org/ 或是 https://mirrors.ustc.edu.cn/rubygems/ 都会出现 SSL 证书问题:

zhangkaizhao@HUMAN-MYTH MINGW64 ~
$ gem sources -a https://mirrors.ustc.edu.cn/rubygems/
Error fetching https://mirrors.ustc.edu.cn/rubygems/:
       SSL_connect returned=1 errno=0 state=error: certificate verify failed (https://mirrors.ustc.edu.cn/rubygems/specs.4.8.gz)

在 Windows cmd 中的 RubyInstaller for windows 的 RubyGems 源也一样:

C:\Users\zhangkaizhao>gem sources -a https://mirrors.ustc.edu.cn/rubygems/
Error fetching https://mirrors.ustc.edu.cn/rubygems/:
       SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://mirrors.ustc.edu.cn/rubygems/specs.4.8.gz)

解决方法

MSYS2

在 MSYS2 中,可以像在 Arch Linux 里一样,通过各自安装这些包:

  • msys/ca-certificates: 用于 msys2

    $ pacman -S msys/ca-certificates

  • mingw32/mingw-w64-i686-ca-certificates: 用于 mingw32

    $ pacman -S mingw32/mingw-w64-i686-ca-certificates

  • mingw64/mingw-w64-x86_64-ca-certificates: 用于 mingw64

    $ pacman -S mingw64/mingw-w64-x86_64-ca-certificates

结果,比如对于 mingw64 :

zhangkaizhao@HUMAN-MYTH MINGW64 ~
$ gem sources -a https://mirrors.ustc.edu.cn/rubygems/
https://mirrors.ustc.edu.cn/rubygems/ added to sources

RubyInstaller for windows

而对于 RubyInstaller for windows 呢?参考这个: http://stackoverflow.com/a/27298259/3449199

先找到 RubyGems 的位置:

C:\Users\zhangkaizhao>gem which rubygems
C:/Ruby22-x64/lib/ruby/site_ruby/2.2.0/rubygems.rb

然后直接将 MSYS2 里的 SSL 证书 pem 文件复制过去即可,比如复制 mingw64 里的:

zhangkaizhao@HUMAN-MYTH MINGW64 ~
$ cp /mingw64/ssl/cert.pem /c/Ruby22-x64/lib/ruby/site_ruby/2.2.0/rubygems/ssl_certs/mingw64_cert.pem

结果:

C:\Users\zhangkaizhao>gem sources -a https://mirrors.ustc.edu.cn/rubygems/
https://mirrors.ustc.edu.cn/rubygems/ added to sources

MSYS2 近来的 repo 同步问题

MSYS2 近来的 repo 同步问题

MSYS2: http://sourceforge.net/projects/msys2/

可能是 SourceForge 调整了 MSYS2 repo 文件的下载链接, 使得这些下载链接被重定向到真正可以下载的位置, 导致使用:

$ pacman -Sy

同步失败,下载得到的 repo 文件是 html 文件。

$ file /var/lib/pacman/sync/*.db

pacman 的配置文件中可以使用 XferCommand 配置选项来指定下载命令, 其中支持 curl 和 wget :

#XferCommand = /usr/bin/curl -C - -f %u > %o
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u

可以使用 curl 的 -L 参数使得下载支持下载链接重定向:

XferCommand = /usr/bin/curl -L -C - -f %u > %o

这样就可以了。

如果还遇上被墙的话,比如我这里就是这样,再加上代理参数, 比如使用 socks5 的 shadowsocks 的话:

XferCommand = /usr/bin/curl --socks5 127.0.0.1:1080 -L -C - -f %u > %o

就可以了。

另外,如果只是 repo 文件会被墙的话,比如我这里,可以在同步完 repo 文件之后, 注释掉这个 XferCommand 配置选项,节省代理消耗。 :-)

OCaml

OCaml

2014,07,10

A record is a collection of labels and types. These labels must be unique within the current module so the type inference engine can infer types correctly.

via: Joshua B. Smith. 2006. Practical OCaml. New York: Apress, pp. 28

(CHAPTER 3 SYNTAX AND SEMANTICS -> Defining Records)

好吧,看到这里就没想再继续学习 OCaml 了啊。。。

2013,12,08 PyCon 2013 珠海,笔记

当场笔记:

http://www.douban.com/photos/album/122033509/

等有空再整理,总结。 :-(

产品开发到底由谁主导?

引言

首先,让我怀念一下我曾经的同事——作为策划的A罗~

云风在《我的编程感悟》中提及项目主导(第13章 开发方法 -> 13.1 失败的经验)经由程序员主导到策划主导,甚至美术、市场人员主导等。

而在这第 13 章中讲到好多的失败的、成功的经验。自从加入程序开发以来经历许多,竟也有些许类似的感受!

这里谈下产品开发主导的感受。

产品设计的核心

一个产品从一开始的闪光 idea 到可以见天日,到底是由谁主导呢?

也许很多人会马上说,“那不是废话吗!肯定是老板啊!”

我觉得这样说,应该是没有经过认真思考的。

我认为云风的观点是值得学习的,一个成功的产品开发的主导是需要多方协作的。

当然,人员越多,沟通成本指数上升。(这是私自认为很有前景的领域,曾经的A罗所在公司的亮点所在。)

不过,这其中,包括老板在内的领导们、市场人员、策划、外观设计、技术开发人员之中,据我经历来说,策划应该是产品设计之中的核心。

为什么这么说呢?

产品策划

首先,在没有经过任何的学习和培训下,我认为产品策划(哪怕只是某个角色担当起了这个重任)的工作至少包括了以下内容:

  • 将领导和市场人员的需求、指导等转化成实际的产品功能特性
  • 产品功能特性的原型设计

这么说吧,一个称职的产品策划应该是最了解产品的。 当然,鉴于局限性,是可以不了解底层是如何实现的,也可以不了解市场处于何种情况,因为这不是他的职责。

在产品开始开发前,所有人都需要和产品策划沟通:

  • 需求:领导、市场人员
  • 外观实现:外观设计人员
  • 底层实现:底层技术开发人员

产品策划需要按照需求,结合技术开发人员的实际能力和反馈,制定一份简洁的策划书。

策划书需要理清楚的内容包括:

  • 目前需求
  • 需求转化成的每项功能特性
  • 原型设计

对于前面两个应该很好理解,最后一个原型设计和外观开发的原型设计有些相似,但是有区分:只需要根据每项功能特性作出蓝图设计。

比如:

  • 对于网站设计:需要规划好大概需要哪些页面来满足需求,这些页面大概需要显示哪些方面的数据。
  • 对于服务接口:需要规划好大概需要哪些服务接口来满足需求,每个服务接口大概需要提供哪些参数、返回哪些数据。
  • ...

这些蓝图的设计,最强烈的建议是拿起笔和纸,手动构思。当然可以使用一些高级的工具,比如 Axure 、 Pencil Project 等。

策划书的审核需要所有人的讨论确定:

  • 领导和市场人员需要确定是否满足了他们的需求
  • 外观设计和底层技术开发人员需要确定是否超出了他们的能力范围
  • 产品负责人(可能就是所谓的“项目经理”?)需要以此确定产品开发各个实施阶段是否符合领导和市场人员的要求

产品的开发并不是从一开始就完全制定好的,总是会随着需求变化而做出变更。

产品的变更

毫无规划的产品设计导致了产品开发的混乱,给人一种无尽任务的感觉。

产品的变更是需要被规划的。这涉及到产品的策划如何做出正确的应对。

正如源代码的管理需要有版本之类的策略,产品的变更需要使用类似里程碑的方式。

每一个被决定的功能特性来自具体的需求,它们需要被正确地安排在每一个阶段的实现中。

就算这些功能特性的决定在后来存在变更,它们也应该能够被规划被调整。

这个调整的过程应该和产品开始时候的商讨、决策类似。

产品策划需要和产品负责人协商每一个阶段需要实现的功能特性以及实现这些功能特性需要花费的时间和精力。

后语

在没有拿出一个设计蓝图,而匆匆将任务扔给某个技术开发人员的做法是很危险的。

就像《我的游戏感悟》中提到的各种失败的经验那样,将产品主导以及工作过多地放置于某一个人之上特别是技术开发人员之上更加危险。

相信没有哪个老板会不希望自己的产品能顺利开发,顺利达到期望。然而不静下心来讨论如何进行产品开发的话,再好的创意也是白搭。

没有人会愿意看到自己的辛苦会被人误解,埋怨甚至嘲笑。

我们需要更好的开发方式、开发流程,需要好的产品策划!

-- 写得有点虎头蛇尾,有点凌乱,有空再整理整理……


updated on 2013,11,23

删去可能被误解为吐槽的内容。

使用 BINARY 存储 *_id

一篇很早以前的文章,好像很有价值:

How FriendFeed uses MySQL to store schema-less data

细心观察,发现使用了 BINARY 数据类型存储各种 *_id ,相信有很多好处:

  • 存储占用空间减小了大概一半,比如:

    >>> len("71f0c4d2291844cca2df6f486e96e37c")

    >>> 32

    >>> len(binascii.a2b_hex("71f0c4d2291844cca2df6f486e96e37c"))

    >>> 16

  • 由于存储占用空间的减少和使用二进制格式,可能带来相关性能的提高,比如查询

  • ...


updated on 2013,07,23 00:28

嗯,刚才看到 CPyUG 的 D.Y Feng 兄弟提到这个:

改善MySQL上16进制标识符性能的5种方法

其中的“三、使用二进制数据存储”就是上面 FriendFeed 使用的!呵呵

翻墙安装 goprotobuf 库

每当被墙挡住的时候,某些人的寿命就又少了一部分(被狠狠地诅咒了又一次)!

今天安装 goprotobuf 库就是这样子。还好有 Tor .

准备 Tor

访问 https://bridges.torproject.org/ 得到当前可用的 bridge , 在 vidalia 中设置好 bridges ,然后就连上了 Tor 匿名网络。

设置 http_proxy

$ export $http_proxy=127.0.0.1:8118

安装

$ go get code.google.com/p/goprotobuf/{proto,protoc-gen-go}

终于不再 Connection reset by peer 了。

Python 嵌套函数本地变量

大家都知道这个:

>>> def g():
>>>    s = 'z'
>>>    def f():
>>>        s = 'k'
>>>        print('f: %s' % s)
>>>    f()
>>>    return s
>>> print(g())

在 Python 2.x/3.x 都会得到:

f: k
z

但是最近同事使用 list 写了一个这样的:

>>> def g():
>>>     s = ['z']
>>>     def f():
>>>         s[0] = 'k'
>>>         print('f: %s' % s[0])
>>>     f()
>>>     return s[0]
>>> print(g())

在 Python 2.x/3.x 都会得到:

f: k
k

这是?


updated on 2013,05,02

其实这个问题主要包括两个方面的原因:

1) Python 调用模型中对参数的传递使用的是传值,不过所传的值不是该参数对象具体的值,而是该参数对象的引用。

http://docs.python.org/2/tutorial/controlflow.html#defining-functions

The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, a new local symbol table is created for that call.

...

[1] Actually, call by object reference would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list).

另外,也有称这种参数传递方式为 call by object 的:

http://effbot.org/zone/call-by-object.htm

2) 在 Python 中变量名只是其所对应的对象的一种引用,而且在对象与变量名的对应关系中使用 copy on write 的方式来优化性能。

要知道一个对象与变量名的关系。在 Python 中变量名与对象是不同的东西。一般来说,通过赋值语句会生成一个对象,但这个对象一般不能直接使用,需要通过一个引用来使用它,即给它一个名字。也就是等号左边是一个变量名,右边是生成对象的代码,因此在执行这条赋值语句后就存在了两个东西,一个是名字,一个是对象。在 Python 中把名字与变量关联起来叫绑定。因此在后面你如果继续对同一个变量名赋值的话,其实是实现了对变量名与新对象的重新绑定,在 Python 中这是允许的,原来绑定的对象如果无人再使用就自动回收,否则就将引用计数减1。而这个对象是无法改变类型的。

copy on write 在重新绑定对象与变量名的时候起作用。

无论对象是不是被作为参数调用并应用到局部作用域,这个 copy on write 方式都发生作用:

>>> # 不可变对象的情况
>>> ss = 'abc'
>>> id(ss)  # -> 36956344
>>> ss = 'xyz'
>>> id(ss)  # -> 59511896
>>> kk = ss  # point to the same object
>>> id(kk)  # -> 59511896
>>> kk = 'rst'  # copy on write
>>> id(kk)  # -> 59547520
>>> id(ss)  # -> 59511896
>>> ss  # -> 'xyz'

>>> # 可变对象的情况
>>> aa = [11,  22]
>>> id(aa)  # -> 59628168
>>> aa.append(33)
>>> id(aa)  # -> 59628168
>>> aa[2] = 44
>>> id(aa)  # -> 59628168
>>> aa = ['x', 'y', 'z']
>>> id(aa)  # -> 60494664
>>> bb = aa  # point to the same object
>>> id(bb)  # -> 60494664
>>> bb[1] = 's'
>>> id(bb)  # -> 60494664
>>> id(aa)  # -> 60494664
>>> bb  # -> ['x', 's', 'z']
>>> aa  # -> ['x', 's', 'z']
>>> bb = [111, 222, 333, 444]  # copy on write
>>> id(bb)  # -> 60483784
>>> id(aa)  # -> 60494664

updated on 2015,12,18

然后,注意这里其实主要是闭包的问题。

在 Python 中闭包的一些文章:

Python闭包详解

http://www.cnblogs.com/ChrisChen3121/p/3208119.html

Python深入04 闭包

http://www.cnblogs.com/vamei/archive/2012/12/15/2772451.html

Python中的闭包

http://www.the5fire.com/closure-in-python.html

有趣的Python闭包(Closures)

http://feilong.me/2012/06/interesting-python-closures

在内部函数bar里面,本地的a = 1定义了在bar函数范围内的新的一个局部变量,因为名字和外部函数foo里面的变量a名字相同,导致外部函数foo里的a在内部函数bar里实际已不可见。

再来说a = a + 1出错是怎么回事,首先a = xxx这种形式,Python解析器认为要在内部函数bar内创建一个新的局部变量a,同时外部函数foo里的a在bar里已不可见,而解析器对接下来对右边的a + 1的解析就是用本地的变量a加1,而这时左边的a即本地的变量a还没有创建(等右边赋值呢),因此就这就产生了一个是鸡生蛋还是蛋生鸡的问题,导致了上面说的UnboundLocalError的错误。

在Python3.x中引入了一个nonloacal的关键字来解决这个问题,只要在a = a + 1前加一句nonloacal a即可,即显式的指定a不是内部函数bar内的本地变量,这样就可以在bar内正常的使用和再赋值外部函数foo内的变量a了。


updated on 2016,01,06

当在内部函数使用 globals()locals() 时候,可能外部函数里的变量尚未被放入闭包中:

via: https://www.python.org/dev/peps/pep-0498/#id25

In the discussions on python-dev [4] , a number of solutions where presented that used locals() and globals() or their equivalents. All of these have various problems. Among these are referencing variables that are not otherwise used in a closure. Consider:

>>> def outer(x):
...     def inner():
...         return 'x={x}'.format_map(locals())
...     return inner
...
>>> outer(42)()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in inner
KeyError: 'x'

This returns an error because the compiler has not added a reference to x inside the closure. You need to manually add a reference to x in order for this to work:

>>> def outer(x):
...     def inner():
...         x
...         return 'x={x}'.format_map(locals())
...     return inner
...
>>> outer(42)()
'x=42'

In addition, using locals() or globals() introduces an information leak. A called routine that has access to the callers locals() or globals() has access to far more information than needed to do the string interpolation.

Guido stated [5] that any solution to better string interpolation would not use locals() or globals().

[4]: Formatting using locals() and globals() ( https://mail.python.org/pipermail/python-ideas/2015-July/034671.html )

[5]: Avoid locals() and globals() ( https://mail.python.org/pipermail/python-ideas/2015-July/034701.html )

Older