为了年少时候的承诺

以前用了很多盗版软件,最大的原因就是太贵,买不起,而不得不承认,正因为其中的一些软件,才让我有了今天的些许成绩。虽然不是自己的个人问题,曾几何时,这是一个普遍的社会现象。如同现在我们到国外,发现东西不贵啊,而且是人家几十年一直这个价格。

不是很懂宏观经济,反正现在可以支配的货币多了,很多软件都买得起了。office 和很多常用的共享软件已经用了很多年正版了,之前一直想入手 adobe lightroom,但是几千的价格还是有点下不了决心,最近发现,原来 adobe 已经学习 microsoft 了,软件可以用和会员结合的年服务费模式,并且有专门只使用 lightroom 和 photoshop 的摄影会员可供选择。

那就不要犹豫了,这个世界是公平的,每个人的贡献,汇聚在一起,力量会很大。如果只是吃吃喝喝混日子,有什么意义呢。

谢谢 lightroom,曾经处理了成千上万张照片,虽然佳作寥寥,但也带来了很多欢乐。

lightroom

2005年那时候,做过很多免费虚拟主机的计划,记得当时的网站叫做理想空间,现在我写一点很简单的开源软件,教教小孩子 python,好像这样更加有趣和有意义。自己年少时候的承诺总是要尽量去履行的。

python 创建模块时候的几个小坑

为了方便和同事们的协同开发,将自己写的有点代码都修改为模块,这几天在更新和测试中还是碰到很多问题。国内 python 开发虽然如火如荼,但是开发模块的人还是非常少,加上国人一般都是不太愿意分享的,只好慢慢看英文资料和测试了。

install_requires 的问题。

在 setup.py 中设置所有模块需要的参数等,其中 install_requires 是用来设置这个模块有什么依赖模块和版本的,但是如果你在 sdist 过程中针对这个 install_requires 报错了,那么最简单的方法是将

from distutils.core import setup

替换为

from setuptools import setup

对于 Pycharm 默认生成的 setup.py,的确生成的是前者,我也不清楚这是不是 pycharm 的 bug。

可以参考这个回答

You are not allowed to edit ‘…’ package information 问题。

在第一次上传 pypi 的时候,或许你会得到这样的错误信息,那么必须先执行:

python setup.py register

然后再执行

python setup.py sdist upload

这样就可以了。可以参考这个回答

setup.py 文件包括其他文件

即便在 MANIFEST.in 文件中包括了想要的测试或者数据文件,我发现还是没有在安装包中有相关的文件,一查资料,原来是要在 setup.py 中设置:

include_package_data=True

这样就可以了。

关于 python 的 __init__.py 最清楚的介绍

在写 python package 的时候,不可避免的和 __init__.py 打交道,查了很多资料,发觉下面的文章是介绍的最清楚的,来源 老王的python ,我重新整理了一下格式:

python 中的 Module 是比较重要的概念。常见的情况是,事先写好一个.py 文件,在另一个文件中需要 import 时,将事先写好的 .py 文件拷贝 到当前目录,或者是在 sys.path 中增加事先写好的 .py 文件所在的目录,然后 import。这样的做法,对于少数文件是可行的,但如果程序数目很多,层级很复杂,就很吃力了。

有没有办法,像 Java 的 Package 一样,将多个 .py 文件组织起来,以便在外部统一调用,和在内部互相调用呢?答案是有的。

主要是用到 python 的包的概念,python __init__.py 在包里起一个比较重要的作用。

要弄明白这个问题,首先要知道,python 在执行 import 语句时,到底进行了什么操作,按照 python 的文档,它执行了如下操作:

第1步,创建一个新的,空的 module 对象(它可能包含多个 module );
第2步,把这个 module 对象插入 sys.module 中
第3步,装载 module 的代码(如果需要,首先必须编译)
第4步,执行新的 module 中对应的代码。

在执行第3步时,首先要找到 module 程序所在的位置,其原理为:

如果需要导入的 module 的名字是 m1,则解释器必须找到 m1.py,它首先在当前目录查找,然后是在环境变量 PYTHONPATH 中查找。PYTHONPATH 可以视为系统的 PATH 变量一类的东西,其中包含若干个目录。如果 PYTHONPATH 没有设定,或者找不到 m1.py,则继续搜索 与 python 的安装设置相关的默认路径,在 Unix下,通常是 /usr/local/lib/python。

事实上,搜索的顺序是:当前路径 (以及从当前目录指定的 sys.path),然后是 PYTHONPATH,然后是 python的安装设置相关的默认路径。正因为存在这样的顺序,如果当前 路径或 PYTHONPATH 中存在与标准 module 同样的 module,则会覆盖标准 module。也就是说,如果当前目录下存在 xml.py,那么执行 import xml 时,导入的是当前目录下的 module,而不是系统标准的xml。

了解了这些,我们就可以先构建一个 package,以普通 module 的方式导入,就可以直接访问此 package 中的各个module 了。

Python 中的 package 定义很简单,其层次结构与程序所在目录的层次结构相同,这一点与 Java 类似,唯一不同的地方在于,python 中的 package 必须包含一个 __init__.py 的文件。
例如,我们可以这样组织一个 package:

package1/
__init__.py
subPack1/
__init__.py
module_11.py
module_12.py
module_13.py
subPack2/
__init__.py
module_21.py
module_22.py
……

__init__.py 可以为空,只要它存在,就表明此目录应被作为一个 package 处理。当然,__init__.py 中也可以设置相应的内容,下文详细介绍。

好了,现在我们在module_11.py中定义一个函数:

def funA():
    print "funcA in module_11"
    return

 

在顶层目录(也就是 package1 所在的目录,当然也参考上面的介绍,将 package1 放在解释器能够搜索到的地方)运行python:

>>>from package1.subPack1.module_11 import funcA
>>>funcA()
funcA in module_11

 

这样,我们就按照package的层次关系,正确调用了module_11中的函数。

细心的用户会发现,有时在 import 语句中会出现通配符 *,导入某个 module 中的所有元素,这是怎么实现的呢?
答案就在 __init__.py 中。我们在 ubPack1 的 __init__.py 文件中写

__all__ = ['module_13', 'module_12']

 

然后进入python

>>>from package1.subPack1 import *
>>>module_11.funcA()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_11

 

也就是说,以 * 导入时,package 内的 module 是受 __init__.py 限制的。

好了,最后来看看,如何在 package 内部互相调用。
如果希望调用同一个 package 中的 module,则直接 import 即可。也就是说,在 module_12.py 中,可以直接使用

import module_11

 

如果不在同一个 package 中,例如我们希望在 module_21.py 中调用 module_11.py 中的 FuncA,则应该这样:

from module_11 import funcA

 

mac osx 下建立 python package 以及在github 上开源项目的操作过程

怎么建立一个 python 包,并且发布到 pypi,有很多文章介绍了。同样,怎么在 github 建立一个开源项目,也不难。

把这两个事情一起做,加上我用 pycharm 来辅助完成 python 包的建立,以及用 source tree 来管理 github 项目,事情可就不少了。

小结一下经验体会:

1 建立 python 包,网上大部分教程没什么问题,如果用 pycharm 会更加容易一些,在菜单 Tools 中,会看到 Create setup.py,pycharm 会做一些目录结构调整、生成最基本的需要的文件,以及输入版本作者之类的事情。

2 文件结构转换为包的形式后,pycharm 很聪明的会在菜单 Tools 中,增加一个 Run setup.py Task。可以节约一些工作量,比如 sdist,这是必须执行的,upload 上传也是必须执行的。不过这里有一个坑,在 sdist 执行好之后,就可以选择 install 命令安装自己的包,然后在程序里面 import 什么都可以了,但是如果这时候你想上传 pypi 可能会报错:

error: no dist file created in earlier command

 

当然,肯定已经在 pypi 注册过用户了,查了不少资料,原来是要先这样操作:

python setup.py sdist upload

 

没有在 pycharm 中找到相应的命令,在终端模式下输入吧。

然后就可以 upload 了。所以,如果你 upload 到 pypi 同样碰到上面的错误,不妨试试看先这样操作一下。

来源这个老外的博客文章,写的很有趣也很清楚。

补充:直接执行上面的命令,应该是连 sdist 和 upload 一起都运行了,这样是最方便的。

running sdist
running check
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default file list)

writing manifest file 'MANIFEST'
creating fish_base-1.0.2
creating fish_base-1.0.2/fish_base
making hard links in fish_base-1.0.2...
hard linking README.txt -> fish_base-1.0.2
hard linking setup.py -> fish_base-1.0.2
hard linking fish_base/__init__.py -> fish_base-1.0.2/fish_base
Creating tar archive
removing 'fish_base-1.0.2' (and everything under it)
running upload
Submitting dist/fish_base-1.0.2.tar.gz to https://pypi.python.org/pypi
HTTP Error 500: Internal Server Error
error: HTTP Error 500: Internal Server Error

 

看这里的操作,当 upload 后,显示了错误的信息,但是到 pypi 上看,已经传上去了,略有奇怪,可能这里的网络不稳定。

3 github 中碰到的问题,就是 https 模式下,用户名密码始终通不过验证,然后换成用 ssh 证书模式,按照 github 上的操作是最靠谱的,并且他们区分了不同操作系统,个人私钥的文件名一定要叫 id_rsa,反正我这里不叫这个就是通不过。
严格按照 github 上的步骤,以及测试 ssh 是否通顺的方法,如果不能通过,肯定是不能用的。

4 在项目的 .git 目录下,有一个 config 文件,可以修改其中的 https 模式到 ssh 模式。

5 osx EI Capitan 在 Finder 中显示隐藏信息的方法和之前版本有所改变:

defaults write com.apple.finder AppleShowAllFiles -bool true
killall Finder  

 

关键是后面那句。

source tree 作为一个免费强大的版本管理软件,没什么好说的,使用起来也很方便。

好了,我要修改代码了,为了试验,所传的项目代码都很烂,需要好好修改一下。

python 3.x 下载说明以及自带编辑器 IDLE 使用

首先到 python 官网,找到下载链接,目前最新版本是 3.5.1,不建议再使用 2.x 系列了。从 download 链接看到下面这个:

python351_install_start

windows 操作系统只需要下载32位版本即可,对于 python 的学习不会有任何影响,mac 电脑下载对应的最新版本就可以了。

以 windows 操作系统举例,下载后,执行安装程序,如下:

python351_install_start

一般情况下不用做任何修改,几分钟就安装好了,如下:

python351_install_finish

安装好后,在开始菜单找到 python 3.5 程序组,看到其中的 IDLE(Python 3.5 32bit),运行后就会出现下面的 python shell:

python_IDLE

可以在这里输入简单的 python 程序,正确的话,会执行,错误的话,会报错。

python_IDLE_run

不过在这个 shell 里面编辑稍微长一点的 python 程序会比较麻烦,所以,可以在 shell 的 File 菜单里面选择第一项 New File,这时候,一个编辑器窗口就出现了。

在编辑器里可以编写比较长的程序,选择菜单 Run 里面的 Run Module,就可以运行程序,结果会显示在一个 shell 窗口中,就像下面这样,注意在运行程序前是需要保存程序文件的:

python_IDLE_edit

python 作为目前几乎是最流行的脚本语言,有各种各样非常多的开发环境,以及我自己非常喜欢的 juypter(ipython),不过其自带 IDLE 和 python shell 对于初学者来说,已经足够了。

为了一些梦想

今天和一位东方财富网的朋友聊到编程语言,原来他以前也是用 delphi 的,我们都感叹道 delphi 的没落。

如今,我已经是 python 的忠实粉丝了。

一些机缘巧合,现在开始教一些小孩子 python,的确作为入门语言,python 非常不错,相对很容易教。

当然,python 也是入门容易精通难,自己也是觉得越学习越觉得不懂,但是这样的感觉很棒,值得努力,到什么高度是一回事情,只要登高即可。

于是对于 python 的学习,就落实到了两个方面,普及和钻研,会逐渐把自己在教小孩子的过程中整理的讲义、各类举例整理出来,分享给大家。而在公司中,随着 python 也用的越来越多,相对复杂的编程技术。

十多年来,一直努力做着这样 knowlege transfer 的事情,之前的理想空间计划,现在的 python教育,或许这是一个不那么实际的梦想,但是我喜欢,有家人朋友支持,也很开心。

情怀

这两年,最用情怀作为卖点的就是锤子了。

有时候想想自己,说来有趣,我从小最计较的情怀就是编程,在很长的时间里,这个几乎就是我的第一爱好了。

除了一开始工作的几年,其实我的工作也基本上可以不编程序,但是总舍不得这个情怀。

rpgmaker mv

从盗版用到正版,其实也不在乎真的靠这个赚钱之类,这就是一种情怀吧,

去年开始学习 python,其实也是放弃了跟随多年的 delphi,这个过程其实也挺难受的,如人生,有舍有得,那么多东西装在心里,怎么容得下新事物呢。

虽然有时候选择的过程是有点痛苦的,也还是充满了未知。

好在,这几年明白,世界是多元化的,人生不是只有左右。

Python中使用 sqlalchemy 访问数据库和简单操作

在我们的数据仓库设计中,python 是我们用来连接各个数据库和应用逻辑的纽带。python 几乎无所不能,反正性能上有要求的就交给 java,要快速开发的逻辑多变的就交给 python。

python 中访问数据库最有名的就是 sqlalchemy 包了。

from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.sql import select, insert

engine = create_engine('mysql+pymysql://macmini:***@192.168.199.***:3306/test?charset=utf8mb4', pool_recycle=3600)
meta = MetaData(bind=engine)
students = Table("students", meta, autoload=True, autoload_with=engine)

conn = engine.connect()

s = select([students])
result = conn.execute(s)

print(s)

for row in result:
    print(row)

 

通过 sqlalchemy 访问 mysql 数据库,需要先创建一个 engine 对象,输入 mysql 的 ip 地址和用户名密码。后面的就简单了。

sqlalchemy 访问数据库可以用 orm 或者称之为 Expression Language 的方法,上面例子里面的 select 方法就是属于 sqlaclchemy 的快速语言方法,s 变量是用来检验的生成的 sql 语句,

看一下结果就很明白了,列出了sql语句(一般是不需要的),以及 select 的查询结果:

SELECT students.id, students.name, students.sex, students.age, students.tel
FROM students

(1, ‘王刚’, ‘男’, 20, ‘13811371377’)
(2, ‘张三’, ‘男’, 30, ‘16512341234’)

下面则是 insert 的用法,是不是非常简洁,这样的写法避免了 sql 语句的啰嗦,抽象起来,就可以用在业务逻辑复杂多变的场景了,即便是所谓写死的业务逻辑,这样也比较容易看懂,而一般的 sql 语句非常不容易调试:

conn.execute(students.insert(), [
    {'name' : '张三', 'sex' : '男', 'age' : 30, 'tel' : '16512341234'},
    ])

 

PyCharm 开发环境中出现中文显示不正常怎么办

说明一下,不是说python程序代码中文显示为,也不是说python程序怎么输出中文,而是 pycharm,这个开发神器有时候也会莫名其妙的让开发环境 ide 里面的中文显示不正常,比如中文的文件名,或者 git 提交的中文注释,都变成了一个个框。

我再mac 下用新版本的 pycharm 5.0.3 ,一切正常,但是到了windows 下,就出现了上面说的问题。解决方法就是到 Settings-Appearance,下面有一个字体选择,修改为 微软雅黑,肯定就没事了,ide 会提示这是覆盖了默认的字体什么的,也不用管了。

好了,中文文件名等都正常了。和 utf-8 之类没有关系。

python和数据库学习笔记-在mac下配置python和mysql开发环境

一个小项目结束,于是可以继续研究。现在研究的课题和大数据有关,数据仓库目前是在vertica上面,然后计划用公有云的方案来处理计算能力的弹性问题,也就是将部分数据从vertica导入到hive+spark中,方案还是庞大复杂的,所以除了设计整个架构以外,也继续要考虑应用端的很多实践。和spark打交道的事情就交给java了,应用层交给php+js,中间最复杂的业务逻辑自然是我现在最为推崇的python了。

好,慢慢开始学习。

任务:

  1. 在mac上搭建一个vmware上的ubuntu虚拟机,安装mysql,这样从mac的开发环境访问,比较接近真实情况
  2. python在mac上设置为可以访问mysql,且不需要安装mysql

安装vmware,我是在 osx 10.11.2 上安装的 vmware 8.0,从 ubuntu 官网上下载的 ubuntu 15.04 desktop 版本,选择 desktop 版本其实作为 server 是不太好的,不过我对linux 的熟悉程度还不够,所以考虑有图形界面比较容易使用。

在虚拟机里面安装 ubuntu 还是比较容易的,然后安装 ubuntu 后再在命令上下安装 mysql:

sudo apt-get mysql-server

 

很多google上的资料说要注意 mysql 的 root 密码之类,我在安装的时候,mysql 是主动提醒要修改 root 密码的。我安装的 mysql 版本是 5.6.27。

在 ubuntu 下比较好用的 mysql 的图形管理客户端是官方的免费的 MySQL Workbench,我安装的版本是 6.2。用这个图形客户端设置用户名、数据库之类都非常方便。

mysql 安装后在默认情况下的确不允许其他电脑连接,这个弄了我很久,很多资料都说的不对,我觉得权限给的很高也不合适,很多资料说到的 bind ip 的修改,我发现是在 /etc/mysql/mysql.conf.d/mysqld.cnf 中修改,去掉 bindip = 127.0.0.1 的设置。

在 vmware 的虚拟机上安装好 ubuntu+mysql 之后,开始在mac 开发环境连接,同样是安装 MySQL Workbench 的 mac 版本,然后就可以测试连接之类,这个方法最方便实用。

这样,比起 localhost 当然是麻烦一点,主要是为之后多环境做好一些准备(开发环境、测试环境、准生产环境和生产环境)。在 mac 上用 xampp 也是不错的,改天再测试,更加适合笔记本电脑。

对于 python 怎么连接 mysql,发现 python 世界真的发展好快,方法很多。

因为准备之后要用 petl 来进行数据库的抽取和处理,所以按照 petl 的推荐,使用 pymysql 这个库。安装用标准的 pip 即可,我用的是conda,方法一样。

mac 开发环境下是不需要安装整个 mysql server 的,但是还是要安装一些驱动的,安装 mysql 标准的 connector,参考这里,下载后,在 mac 这里是一个 dmg 安装包,安装后,可以理解为 mysql 的驱动程序就安装好了。

import pymysql

connection = pymysql.connect(host='192.168.***.***',
                             user='***',
                             password='***',
                             db='test',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

cur = connection.cursor()

cur.execute('select * from students')

for data in cur.fetchall():
    print(data)

 

当然这个用法是比较简单的,输出结果,运行ok

{‘tel’: ‘13811371377’, ‘sex’: ‘男’, ‘id’: 1, ‘age’: 20, ‘name’: ‘王刚’}

这个demo数据库的建立参考了这里,一个不错的mysql的基础教程。

大致这样,真实的开发项目会越来越复杂,且数据库应用的复杂度比独立应用高很多,希望这些经验能够给初学者们启发。

———————–后续补充

看到廖雪峰网站,上面有非常不错的python 2和3 的教程,对于安装mysql connector 有更加简单的办法

$ pip install mysql-connector-python --allow-external mysql-connector-python

 

以及非常简明实用的mysql 测试:

# 导入MySQL驱动:
>>> import mysql.connector
# 注意把password设为你的root口令:
>>> conn = mysql.connector.connect(user='root', password='password', database='test')
>>> cursor = conn.cursor()
# 创建user表:
>>> cursor.execute('create table user (id varchar(20) primary key, name varchar(20))')
# 插入一行记录,注意MySQL的占位符是%s:
>>> cursor.execute('insert into user (id, name) values (%s, %s)', ['1', 'Michael'])
>>> cursor.rowcount
1
# 提交事务:
>>> conn.commit()
>>> cursor.close()
# 运行查询:
>>> cursor = conn.cursor()
>>> cursor.execute('select * from user where id = %s', ['1'])
>>> values = cursor.fetchall()
>>> values
[('1', 'Michael')]
# 关闭Cursor和Connection:
>>> cursor.close()
True
>>> conn.close()