你好,欢迎光临我的博客!

我是一名使用Python的程序员,这是我的github。平时喜欢玩各种电子游戏,这是我的psn:CenterRight这个博客用来分享我的生活、心得以及有关计算机的技术内容。除特殊说明外均采用CC0创作协议(任何人可以自由地复制,修改,分发和演出——甚至用于商业目的,而不必署名)但是转载建议保留原文链接以让读者看到最新的版本。本站所有内容仅代表本人观点,与我的雇主无关,并且会永远保持独立性不受任何组织和公司的影响。如果我们有共同兴趣,或者你遇到了麻烦,可以通过右边的电子邮箱联系我。也欢迎留言和订阅!

介绍Python2和Python3的兼容库six

Python2和Python3有很大的不同,six这个库为此提供了一个兼容的方案。使用six写的代码可以不用修改就运行在Python2或Python3上。注意这个six并不是让Python2写的代码兼容Python3,如果你需要迁移工具,那么你要找的是2to3。如果你的代码需要同时需要运行在Python2和Python3上,那么你就需要six!

原理其实很简单,six对Python2和Python3的名字等做了统一,比如Python2的字符串叫str,Python3叫unicode,那么就可以使用six.text_type。如果运行在Python2上,six.text_type就是unicode,如果运行在Python3上,six.text_type就是str

six库只有一个文件:six.py。这样做可以方便地拷贝到你的项目中。也可以使用pip安装。

(为什么叫six? 因为2 * 3 = 6。为什么不是+,因为*更牛逼)

下面讲一下six有哪些功能。

统一了Python2和Python3的类型

如上文提到的,使用six中的类型,能同时在Python2和Python3中正确运行,就不用自己在写代码的时候自己判断到底是Python2的unicode还是Python3的str了!

Python2:

Python3

(由于iPython不再支持Python2,所以博主用的REPL for python2是默认的,但是在这里不影响结果)

内部对象属性的重命名

Python3修改了一些解释器内部属性的名字,例如Python2的dictionary.iterlists()在Python3中变成了dictionary.lists(),(讲真我觉得Python3的名字改得好!)。

使用six可以同时兼容这两种名字,但是需要将调用的格式改为 six.iterlists(dictionary, **kwargs)

全部的名字兼容可以参考文档。(话说我不太明白为什么保留的是Python2的名字,不用Python3的)

移动模块的位置

Python3重新组织了很多模块的位置,例如Python2的HTMLParser,在Python3中是html.parser。

我们可以使用six导入:

其他

其他的内容可以在官方的文档找到,基本上就是通过six来调用,而不是自己对Python判断。包括:

  • 提供了二进制和文本数据的兼容
  • uniittest assert的兼容
  • urllib库改动的兼容
  • 高级的自定义move

参考

https://pythonhosted.org/six

 

我的WordPress全站HTTPS啦

终于,本站的强制HTTPS已经开启了,所有的HTTP流量都会被强制转向HTTPS。

虽在早在去年我就申请了HTTPS证书,也更换了独立ip支持了HTTPS,但是并没有强制开启HTTPS,因为我发现根据网上的教程设置.htasccess会失败。后来发先用了really simple SSL插件可以做到https://kawabangga.com跳转到HTTPS,还能帮你将站内绝对路径的链接自动换成HTTPS,看起来不错,就没再管。但是一直有一个遗留问题就是,https://www.kawabangga.com是跳不过去的。

今天小红老师帮我调了一下,最后发现了问题所在。不得不说,姜还是老的辣,要是我自己调我觉得永远搞不定。

问题描述:本在在西部数码的虚拟空间上,有独立ip,支持HTTPS访问,但是HTTP访问www不会跳转到HTTPS。

首先,我们按照网上普遍的教程,在.htaccess(这是apache的配置文件)写:

会发生无限重定向,浏览器无法打开网页。所以看起来是80端口判断永远为真。然后尝试了各种别的判断条件,比如:

也还是不行。

这时候,小红老师说,不是条件判断不正确,而是到你机器上的流量永远是HTTP流量。虽然使用了HTTPS协议,但是空间提供商在内网没有必要使用HTTPS(HTTPS有加密过程更加消耗资源),所以内部是使用HTTP传输数据的。HTTPS包到达空间商的时候,空间提供商使用HTTP协议将此包转发到你的虚拟空间上(就是HTTPS外面套了一层HTTP),所以到达apache的流量永远都是HTTP流量,就发生了无限重定向。

这时候我才发现,原来西部数码自己提供了一个设置方法(放在一个不知名的小页面上,坑),如下:

果然,可以发现这里使用的参数是HTTP:From-Https,是自定义的一个参数!

另外还有一个小插曲,多次修改.htaccess的时候,小红老师看见我把所有的参数都删掉还震惊了一下,我自信的说这些我都不知道是什么,没用。于是部署好HTTPS的跳转之后,除了首页所有的页面都404了……

原来我设置了伪静态,.htaccess里面需要做相应的设置的…… 最后的正确配置如下:

终于一切都正常了。这是我一年来的一块心病啊,终于解决了。

博客四年了,停靠在西部数码也有三年了,同事们都对虚拟空间,wordpress这种东西嗤之以鼻,不过我觉得挺好的。这个博客我上来除了写东西之外几乎没有花很多精力维护,有什么问题客服解决的也很及时。虽然有很多坑,但是我觉得VPS的坑更多。况且四年前我的技术维护vps肯定有很多安全问题。这几年来wordpress的写作体验一直在提升,我很满意。对博客的SEO,amp等新技术也支持的比较好。国外的vps速度慢,国内的需要备案,对我来说选择就很有限了。所以综上看来,这几乎是我最好的选择。还是多总结,能给自己带来收获,一年多一百少一百的倒无所谓。

 

理解Python的import

Python的import是一个使用非常频繁的操作,这是在一个模块中使用另一个模块的代码的操作(几乎所有的语言都有类似的语句)。import语句是最常用的方法,但不是唯一的方法,还有importlib.import_module() 和 __import__() 等。本文解释import语句。

import做了两件事情:

  1. 搜索该名字的module(其实使用的还是内置的__import__()方法)然后初始化一个对象
  2. 将结果与本地的一个变量名绑定(默认就是这个module的名字)。

意味着,这两句是等价的:import package as pk 和 pg = __import__('package')

值得注意的是,只调用__import__()只会执行搜索动作,初始化module对象,最后丢掉该对象(因为没有赋值操作)。这点很容易将内置的__imoprt__()方法和import语句搞混。

一、Packages

Python中只有一种module类型(type),所有的module,无论是C语言实现的,还是Python实现的,还是别的,都是这种了类型。为了使名字空间有等级,Python又有packages的概念。注意这里只是一个“概念”而并不是类型,packages只是一种特殊的“module”。官方文档中将packages比作文件系统的文件夹,module比作文件(但又不完全是)。所有的package都是module,而并不是所有的module都是package。

Python的package又有两种:

Regular package

Regular package就是一个包含 __init__.py文件的文件夹。当此包导入的时候,会执行这个__init__.py文件,然后就可以包名访问包内的名字了。例如下面的文件结构:

当导入parent.one时会执行parent/__init__.pyparent/one/__init__.py

Namespace package

这是PEP 420提出的。

Namespace package由各种不同的部分(portions)组成。portion可以是zip文件,可以使网络上的资源,可以是文件系统中某个位置的资源。Namespace package在文件系统中可能没有实际的文件来表示,可能是虚拟的module。

# TODO read 420 理解namespace

下面来讲import的搜索顺序。

二、搜索

开始搜索之前,需要一个“合适的名字”(来自import语法或者__import__()函数等),即一个通过点分隔的路径名。比如foo.bar.baz,Python会先导入foo,然后导入foo.bar,然后导入foo.bar.baz,如果中间有任何失败,就会抛出ModuleNotFoundError

缓存(sys.modules)

import首先搜索的地方是sys.modules,此为一个键值对的mapping,作为一个缓存,保存了中间形式的路径。所以如果之前import了 foo.bar.baz,那么sys.modules中就会存在foo, foo.bar, foo.bar.baz。每一个名字都对应一个module对象。

import的时候,如果在sys.modules中找到就会返回这个module对象,import过程结束。如果根据key找到了,但是value是None,就会抛出ModuleNotFoundError,如果key不存在,就继续搜索过程。

sys.modules是可写的,删除任何key并不会销毁对象(因为可能别的模块引用了这个模块),但是你可以将value设置为None强制抛出ModuleNotFoundError。下面的代码展示了这个操作(注意使用ipython结果不同,ipython在启动的时候import 了re库)。

要注意的是,如果你有module对象的引用(在sys.module的缓存),但是重新import了module对象,这两个module不会一致。也就是说你再引用一遍,代码中的该module还是从sys.module中的,所以你拿不到新的module。但是使用importlib.reload() 就可以将改module对象重新初始化一遍。这在REPL中测试代码的时候比较实用。

Finder和Loader

如果在缓存(sys.module)中没有找到的话,python就开始import机制来导入这个包。Python的import协议包括两部分:Finder和Loader。只要实现了这两部分,就算是一个importer,importer如果发现自己可以导入目标包的话,就会返回他们自己。顾名思义,Finder的任务是定位包,并不做载入的部分,Loader做真正载入包的工作。Python有三个默认的importer:一个可以导入build-in module,第二个可以导入frozen module, 第三个可以搜索import path。

三、加载

加载过程的伪代码如下:

注意一下细节:

  • sys.module已经存在目标模块的名字,import直接返回此模块
  • 在Loader执行模块代码之前,先将其放入到sys.module。这一点非常重要,可以防止循环导入(模块可能在代码中导入该模块自己)。
  • 如果loading失败,失败的模块(只有失败的模块)会从sys.module删除
  • 在module创建但是执行代码之前,import会设置 import-related 模块属性,作为后续的总结
  • 模块执行的部分才是模块的名字空间真正暴露的时候,这部分完全由loader处理。
  • loading的时候创建的模块、传入exec_module()的模块可能并不是最后返回的模块

Loader

Loader提供了loading最重要的部分:模块的执行。import机制会调用importlib.abc.Loader.exec_module(),参数只有一个,要执行的module对象。其返回值被丢弃。Loader必须满足两个要求:

  • module必须是一个Python的module对象,Loader必须在module的全局名字空间下(module.__dict__)执行module的代码
  • 如果不能执行代码,必须抛出ImportError,其余所有异常都会被忽略

子模块

当子模块的loading执行的时候,将和父模块的名字空间绑定。参考下例:

导入foo将使spamspam.foo属性:

就先写到这里,其实还有一个比较重要的话题就是模块的搜索顺序,以及子模块之间如何组织。新手尝尝遇到在子模块中遇到不能import其他模块的问题,以后再写吧。

彩蛋

import this可以看到Zen of Python

import antigravity可以看到一幅漫画

参考和了解更多

  1. python文档:https://docs.python.org/3/reference/import.html
  2. import hook和meta path
 

推荐《Hymn to life》

推荐一首音乐,一共11分钟多的音乐,前半段是Timo的音乐,后半段是卓别林在《大独裁者》中的演讲。

《大独裁者》是卓别林自导自演的一部电影,演讲呼吁人类消灭独裁和统治,追求幸福和自由,消灭国家之间的界限,鼓励士兵不要听命于愚蠢的统治,不要收体制的禁锢,鼓励进步,但是不要被机器占据了内心。

音乐链接:http://music.163.com/#/m/song?id=19275252

演讲搬运:

《Speech by Charlie (Charles) Chaplin (1889-1977) from The Great Dictator movie (1940)》
查理·卓别林(1889-1977)在《大独裁者》(1940)中的演说

I’m sorry but I don’t want to be an Emperor – that’s not my business
很抱歉,我不想做统治者——我对此毫无兴趣

I don’t want to rule or conquer anyone.
我不想统治任何人,也不想征服任何人

I should like to help everyone if possible, Jew, gentile, black man, white.
如果可以的话,我愿意帮助每一个人,不管是犹太人,非犹太人,黑人,还是白人

We all want to help one another, human beings are likethat.
我们都乐意相互帮助。这是人类的天性

We want to live by each other’s happiness, not by each other’s misery.
我们都乐意生活在他人的幸福之中,而不是眼看着他人痛苦

We don’t want to hate and despise one another.
我们都不愿互相仇恨,互相歧视

In this world there is room for everyone and the good earth is rich and can provide for everyone.
在这个世界上,有足够的空间让每个人得以生存,而土地是丰饶的,可以使每一个人都丰衣足食

The way of life can be free and beautiful.
生命可以是自由的,美好的

But we have lost the way.
但我们失去了这样的生活

Greed has poisoned men’s souls – has barricaded the world with hate;
贪婪毒害了人类的灵魂——它把世界锁在仇恨当中

has goose-stepped us into misery and bloodshed.
它操纵的军队迈着正步,将我们领入痛苦与杀戮

We have developed speed but we have shut ourselves in:
我们发展了速度,却孤立了自己

machinery that gives abundance has left us in want.
机器为我们提供了更多可能,却给我们带来了更多欲望

Our knowledge has made us cynical, our cleverness hard and unkind.
学识把我们变得刻薄,才智把我们变得冷酷无情

We think too much and feel too little: More than machinery we need humanity;
我们思考得太多,感受得太少;然而我们需要的是人性,而不是机械性

More than cleverness we need kindness and gentleness.
是温和友善,而不是才智

Without these qualities, life will be violent and all will be lost.
少了这些品质,生命将陷于暴戾,而我们将丧失一切

The aeroplane and the radio have brought us closer together.
飞行机和收音机将我们联系得更加紧密

The very nature of these inventions cries out for the goodnessin men,
这类发明的性质本身就在呼唤人类的善良

cries out for universal brotherhood for the unity of us all.
呼唤全世界的友爱团结

Even now my voice is reaching millions throughout the world,
就像现在,我的声音传向世界各地无数人们的耳中

millions of despairing men, women and little children,
传向无数的绝望的人们:男人,女人,孩子

victims of a system that makes men torture and imprison innocent people.
所有在这个折磨和禁锢无辜者的体制下承受牺牲的人们

To those who can hear me I say Do not despair.
所有能听到我声音的人们,请听我说,不要绝望

The misery that is now upon us is but the passing of greed,
我们现在所承受的不幸,仅仅是来自一部分人的贪婪和痛苦

the bitterness of men who fear the way of human progress:
他们害怕的是当今人类的进步

the hate of men will pass and dictators die, and the power they took from the people,
人们的仇恨终会消逝,独裁者也注定会死去,而他们从人民手中掳走的权利终

will return to the people and so long as men die, liberty will never perish…
将交还给人民,只要我们不畏牺牲,自由就永远也不会消失

Soldiers – don’t give yourselves to brutes, men who despise you,
战士们!别听命于残暴的畜生——他们蔑视你们

enslave you – who regiment your lives, tell you what to do, what to think and what to feel,
奴役你们,控制你们,告诉你们怎样行事,怎样思考,甚至怎样感受

who drill you, diet you, treat you like cattle, use you as cannon fodder!
他们训练你们,供养你们,像牲口似的对待你们,把你们视如炮灰

Don’t give yourselves to these unnatural men, machine men, with machine minds and machine hearts!
别听命于这些变态的人——这些有着机器头脑、机器心脏的机器人

You are not machines! You are not cattle! You are men!
你们不是机器,不是牲口,你们是人

You have the love of humanity in your hearts.
你们心里拥有的是人性之爱

You don’t hate – only the unloved hate – the unloved and the unnatural.
你们心里没有仇恨,只有得不到爱、丧失理性的人才会心怀仇恨

Soldiers – don’t fight for slavery, fight for liberty!
战士们!不要为了奴役而战!要为自由而战!

In the seventeenth chapter of Saint Luke it is written the kingdom of God is within man –
《路加福音》第十七章里写着,上帝的国度属于人类

not one man,
它不属于某一个人

nor a group of men – but in all men – in you!
不属于某一个集团,它属于全人类!属于你!

You the people have the power, the power to create machines, the power to create happiness!
人民啊,你们拥有权力,你们能创造机器,创造幸福!

You the people have the power to make this life free and beautiful,
人民啊,你们能活得自由活得美好

to make this life a wonderful adventure!
能享受生命这一场奇妙的旅程!

Then in the name of democracy let us use that power – let us all unite!!!
因此,让我们以民主的名义行使这种权力,让我们全体团结起来

Let us fight for a new world, a decent world that will give men a chance to work,
为一个崭新的世界而战,那是一个美好的世界,

that will give you the future and old age and security.
它使壮有所用,少有所求,老有所安

By the promise of these things, brutes have risen to power,
正是因为许下了这样的承诺,一群野蛮人窃取了人民的权力

but they lie!
但他们完全是在撒谎!

They do not fulfil their promise, they never will!
他们根本没能履行那些承诺!并且永远不会!

Dictators free themselves but they enslave the people!
独裁者只是让自己享受自由,却奴役他的人民

Now let us fight to fulfil that promise!
现在就让我们自己起来战斗,来兑现承诺

Let us fight to free the world, to do away with national barriers, to do away with greed,
让我们起来战斗,解放全球!

with hate and intolerance!
去消灭国家的界限!去消灭国家的界限!消灭贪欲,消灭仇恨,消灭蔑视!

Let us fight for a world of reason,
让我们为一个理性的世界而战

a world where science and progress will lead to all men’s happiness.
让科学与进步为全人类造福

Soldiers – in the name of democracy, let us all unite!!!
战士们,让我们以民主的名义团结起来!

 

两个美食家

在德国的时候,某天心血来潮跟欣说,我们把劳特林根的餐厅都去吃一次吧。最后发现,原来这个地方不大,却有那么多好吃的地方,直到最后也没有全部去过。

小镇上有座叫Achalm的小山,我们经常去爬,山脚下有一家中餐厅。有次下山的时候太累了,就在那里吃的。餐厅的老板是个中国人,告诉我们他接手这个餐厅不久,在我们的学校旁边坐4路车可以直接到这里,欢迎我们以后常来玩。我们俩觉得他话太多了,而且菜不也是很好吃,不是很正宗的中餐。以后就再也没有去过。

还有一次下山的时候,路过一个河边的餐厅,紧靠岸边,看起来非常漂亮,就想下次来这里吃吧。后来发现,这原来是一家非常传统的德国餐厅,有很正宗的烤肉和黑啤,配土豆泥。餐厅装修很好,也很大,门口的位子靠河岸,景色不错。里面进去是一个很大的餐厅,还有酒吧。价格也偏高一些,两个人要40欧。烤猪肉比较好吃,一人份刚好吃的很饱。烤肉吃过一次,还有次来这里点了黑啤,还有一次来这里点了个披萨,这里的披萨是方形的,放在一个板子上,很神奇,味道不好。

在德国吃到味道不错的中餐比较难,一般的中餐馆味道跟我们学校的餐厅差不多。不过有一家不错,在sdattmitte,叫做“银座”,听起来像日本餐厅,其实也卖寿司,不过是中国人开的。餐厅分两层,不是上下两层,是平行的两层,一层高一层底而已。高的上面是回转寿司,貌似是15欧,下面的可以点中国菜。水煮鱼特别好吃,记得好像是15欧。第一次吃好像是和欣去法国旅行之前,那时候心情比较浮躁,就像快点出发。不过这个火锅鱼让人即使在烦躁的心情也能吃的下去。稍有点辣,肉很多,点着一个菜够两个人吃的。两个人冲着火锅鱼去吃了好几次。还有一次去尝试了回转寿司,我觉得不是很新鲜,欣倒是吃的很起劲,一边吃一Bianc边算自己已经吃了多少钱的,很可爱。那次不好吃也吃的很撑。

在一起一个月的时候,去了一家西班牙餐厅,朋友推荐的。惊讶的发现,这么小的一家餐厅,并且仅此一家的餐厅,竟然有自己的网站!其实后来发现这并不是一家正规意义的餐厅,更像是一个酒吧,提供叫做tapas的东西,反正最后也是吃饱了,感觉味道还好,啤酒不错。以后也没去过。

就写到这里吧,一年前创建的草稿了,今天才想起来写完。其余还去了很多,都记不太清了。

刚在一起的时候,我说以后每天给你做早饭,这一年来都没下过厨了。十月一搬新家,重新开始下厨吧,菜谱一点一点记下来。