wzyplus

wzyplus 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

程序员

个人动态

wzyplus 发布了文章 · 2015-05-17

[Hi Python] How to reverse a list

Python中反转一个列表的方法不止一个,这里总结一下。

[::-1]

python>>> l = [1, 2, 3, 4]
>>> a = l[::-1]
>>> a
[4, 3, 2, 1]
>>> l
[1, 2, 3, 4]

reverse

python>>> l = [1, 2, 3, 4]
>>> l.reverse()
>>> l
[4, 3, 2, 1]

list的reverse方法将list本身反转,并且返回值是None。

reversed

python>>> l = [1, 2, 3, 4]
>>> reversed(l)
<listreverseiterator object at 0x10de40f10>
>>> for i in reversed(l):
...     print(i)
... 
4
3
2
1

reversed返回的是listreverseiterator并不是一个新的list,这个函数不会改变list本身。

查看原文

赞 0 收藏 1 评论 0

wzyplus 发布了文章 · 2015-05-03

总是出问题的Crontab

最近用Python写了一些数据统计的脚本,并使用crontab自动执行,但是配置crontab总是要过几个坑才行的,这里总结一下这次遇到的坑。

输出

要将crontab命令的输出记录到日志文件中,可以使用重定向,不仅要重定向stdout也要重定向stderr,因为Python解释器会将异常输出到stderr。示例:

$HOME/path/to/script > $HOME/log/file 2>&1

环境变量

crontab会以用户的身份执行配置的命令,但是不会加载用户的环境变量,crontab会设置几个默认的环境变量,例如SHELL、PATH和HOME等,一定要注意PATH可不是用户自定义的PATH。

我们往往会在.bash_profile文件中定义一些全局的环境变量,但是crontab执行时并不会加载这个文件,所以你在shell中正常执行的程序,放到crontab里就不行了,很可能就是因为找不到环境变量了。要解决这个问题只能是自己加载环境变量了,可以在shell脚本中添加source $HOME/.bash_profile,或者直接添加到crontab中。

0 12 * * * source $HOME/.bash_profile && $HOME/path/to/script > $HOME/log/file 2>&1

路径

我们在写脚本时往往会使用相对路径,但是在crontab执行脚本时,由于工作目录不同,就会出现找不到文件或者目录不存在的问题。

解决方法是脚本中使用绝对路径或者在执行程序前切换工作目录,例如直接在crontab命令中切换工作目录:

0 12 * * * source $HOME/.bash_profile && cd $HOME/path/to/workdir && ./script > /HOME/log/file 2>&1

编码

我写的Python程序中输出了一些中文(编码是utf-8),在shell中直接执行没有问题,但是crontab执行时出现了UnicodeEncodeError的错误,Google了一下发现这个问题不仅仅是在crontab中会出现,在使用管道或者重定向的时候都会出现这个问题,原因是编码不同。

在终端中直接执行Python程序时,Python会将输出内容自动编码为终端所使用的编码,我使用的终端编码是utf-8,所以不会出错,输出的内容也是正常的。但是在使用管道或者重定向时,编码格式为ascii,Python会用ascii编码格式去encode输出的字符串,但是字符串的编码使用的时utf-8,所以会出现UnicodeEncodeError的错误。

解决方法:
方法一:在程序中输出的字符串都加上encode('utf-8')
方法二:在crontab中加上PYTHONIOENCODING=utf-8,将Python的stdout/stderr/stdin编码设置为utf-8。

查看原文

赞 4 收藏 13 评论 2

wzyplus 回答了问题 · 2015-04-07

解决很简单的几句python代码,为什么直接Process finished with exit code 2呢?

运行的时候没有加参数

关注 4 回答 3

wzyplus 回答了问题 · 2015-04-06

解决go语言和c语言写的程序通信问题

不知道题主的web server和硬件之间能够通过什么方式连接,我想有以下这几种情况。
如果是在同一台机器上的直接调用C函数或者动态库即可。
如果是通过串口连接,server将命令通过串口发送给设备,设备接收串口数据,然后实现相应的功能。
如果通过网络连接,server和设备之间可以保持一个长连接,server通过socket将数据发送到设备。

关注 1 回答 2

wzyplus 回答了问题 · 2015-04-06

解决有什么好用的MAC平台上的Python IDE?

简单的程序Sublime Text,复杂的程序用PyCharm,另外在Retina屏上eclipse太丑了。

关注 24 回答 19

wzyplus 发布了文章 · 2015-04-06

开始使用Docker

这是在MAC上的一次从零开始学Docker的实践,如果想知道的更多,请阅读官方文档或者Docker —— 从入门到实践,本文的核心科技是动手

Docker是基于Linux Container技术的,并不支持原生的Mac系统,Mac上的Docker是运行于一个Linux虚拟机内的。所以可以在Mac上装个VirtualBox,然后安装一个Linux发行版(例如CoreOS),之后所有的操作就在Linux中进行了。但是这种方法操作起来太麻烦了,我可不想每次使用Docker的时候都启动VirtualBox,然后启动Linux虚拟机,再ssh到虚拟机上,能不能让程序自动的执行这一系列操作。

还好已经有这样的程序了,Boot2Docker是你的好帮手^_^。

安装

使用HomeBrew安装Boot2Docker:

shell$ brew install boot2docker

程序会自动安装Docker客户端和Boot2Docker,网络不好的话喝杯咖啡再回来看看,不行的话多试几次,地址被墙的话请科学上网。

使用

初始化Boot2Docker:

shell$ boot2docker init

如果没有ISO镜像的话,会自动下载。初始化只需要执行一次。

启动Boot2Docker:

shell$ boot2docker start

显示环境变量:

shell$ boot2docker shellinit
Writing /Users/wzy/.boot2docker/certs/boot2docker-vm/ca.pem
Writing /Users/wzy/.boot2docker/certs/boot2docker-vm/cert.pem
Writing /Users/wzy/.boot2docker/certs/boot2docker-vm/key.pem
    export DOCKER_HOST=tcp://192.168.59.103:2376
    export DOCKER_CERT_PATH=/Users/wzy/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1

显示的结果会和你的电脑上的结果不同。

设置环境变量:

shell$ eval "$(boot2docker shellinit)"

这个设置只针对当前会话有效,当你重新打开一个会话后必须再次设置。
或者直接修改.bashrc或者.zshrc,添加boot2docker shellinit结果中的export语句。

运行docker version没有任何错误的话,说明Docker客户端环境已经配置好了,接下来就可以使用Docker了。

练习

下面我们在Docker中启动一个Nginx服务器。

shell$ docker run -d -P --name web nginx

由于本地没有nginx镜像,docker会自动从公共仓库中下载nginx镜像并运行,下载的内容大概有100M。

shell$ docker ps

查看正在运行的docker容器。

shell$ docker port web
443/tcp -> 0.0.0.0:49153
80/tcp -> 0.0.0.0:49154

查看端口的映射关系。

通过浏览器打开localhost:49154,发现无法访问,这并不是服务器没有启动,而是docker端口映射中的0.0.0.0并非是我们的电脑,而是运行Docker的Linux虚拟机,即docker将nginx监听的80端口映射到了虚拟机的49154端口,我们要访问的是虚拟机的49154端口,虚拟机的地址可以通过命令boot2docker ip获得。

shell$ boot2docker ip
192.168.59.103

访问192.168.59.103:49154即可。

停止并删除容器:

shell$ docker stop web
$ docker rm web

再多一点

到这里我们已经亲自感受了Docker,下面还需要进一步学习。

查看原文

赞 0 收藏 19 评论 2

wzyplus 发布了文章 · 2015-04-06

在Mac上使用Nginx和FastCGI部署Flask应用

最近在学习Flask,本文介绍一下如何部署Flask开发的应用,同时也学习一下Nginx的使用,这只是在Mac上的一个实验。

应用

这里使用的应用就是官方的文档中给出的Flaskr

安装Nginx

使用HomeBrew安装Nginx:

shell$ brew install nginx

HomeBrew会自动安装Nginx及其依赖的程序。在我的电脑上安装的是Nginx 1.6.2,配置文件的路径是/usr/local/etc/nginx/nginx.conf

启动Nginx的命令:

shell$ nginx

Nginx的默认端口是8080,用浏览器打开localhost:8080,显示如下所示的页面说明Nginx已经工作了。

配置Nginx

修改Nginx的配置文件:

server {
    listen 80;
    server_name localhost;
    charset utf-8;

    location / { try_files $uri @flaskr; }
    location @flaskr {
        include fastcgi_params;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param SCRIPT_NAME "";
        fastcgi_pass unix:/tmp/flaskr-fcgi.sock;
    }
}

重新启动Nginx:

shell$ nginx -s quit
$ sudo nginx

因为使用了80端口,启动Nginx时需要加上sudo

启动完成后,访问localhost

访问时出现了错误,这是因为我们的应用还没有启动。

FastCGI Server

Nginx是一个静态WEB服务器,不能直接运行我们的Python应用,当Nginx接受到请求时,会通过FastCGI转发给我们的应用,应用是运行在FastCGI Server上的,这个server接收Nginx的请求并调用我们的程序,将结果返回给Nginx,Nginx再将结果返回给用户。

我们要使用的FastCGI Server是flup,安装方法:

shell$ pip install flup

在应用目录下创建一个fcgi文件,例如flaskr.fcgi:

Python#!/usr/bin/python
from flup.server.fcgi import WSGIServer
from flaskr import app

if __name__ == '__main__':
    WSGIServer(app, bindAddress='/tmp/flaskr-fcgi.sock').run()

同时给fcgi文件可执行的权限:

shell$ chmod +x flaskr.fcgi

手动启动server:

shell$ screen
$ ./flaskr.fcgi

使用screen使server在后台运行,或者:

shell$ nohup ./flaskr.fcgi &

再次访问localhost就可以看到我们的应用了。

遇到的问题

第一次运行FastCGI server后,任然无法访问,查看Nginx的日志后发现Nginx服务器没有权限访问socket文件,修改nginx.conf添加user配置:

user wzy;

启动的时候Nginx报错:

nginx: [emerg] getgrnam("wzy") failed in /usr/local/etc/nginx/nginx.conf:2

Google一下后发现要加上用户组才行,改成这样:

user wzy wheel;

再次启动Nginx后一切正常了。

Nginx配置项user的使用方法:

Syntax: user user [group];
Default: user nobody nobody;

如果忽略group,Nginx会使用和user名称一样的用户组,例如我设置user wzy,那么Nginx启动的时候会去查找用户组wzy,我的电脑上没有这个用户组,所以Nginx会报错。

查看原文

赞 3 收藏 11 评论 0

wzyplus 发布了文章 · 2015-04-06

Python Socket Programming

本文介绍使用Python进行Socket网络编程,假设读者已经具备了基本的网络编程知识和Python的基本语法知识,本文中的代码如果没有说明则都是运行在Python 3.4下。

Python的socket功能封装在socket库中,要使用socket,记得先import socket,socket库的详细介绍参见官方文档

创建Socket

首先创建一个socket,使用socket库中得socket函数创建。

Pythonimport socket

# create an INET, STREAM socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

例子中创建了一个TCP socket,socket.socket函数的前两个参数的默认值是socket.AF_INETsocket.SOCK_STREAM,创建TCP socket时可以直接写成socket.socket()

连接服务器

使用socket的connect函数连接到服务器,以下几种参数都是合法的。

Pythons.connect(('localhost', 8000))
s.connect(('127.0.0.1', 8000))
s.connect(('www.baidu.com', 80))

发送数据

发送数据有两个方法sendsendallsend不能保证所有的数据都发送完了,它会返回已发送数据的长度,程序要循环发送数据直到所有数据都已发送完毕。

Pythondef mysend(s, msg):
    total_len = len(msg)
    total_sent = 0
    while total_sent < total_len:
        sent = s.send(msg[total_sent:])
        if sent == 0:
            raise RuntimeError("socket connection broken")
        total_sent += sent

sendall能够保证所有的数据都已发送完毕,除非发送过程中出现了错误,它实际上也是循环发送数据直到所有数据发送完成。

这里还要讲一个需要特别注意的地方,从一个例子开始吧:

Pythonimport socket
s = socket.socket()
s.connect(('www.baidu.com', 80))
s.sendall('test')

都是上面讲过的东西,没什么特别的,分别在Python 2和Python 3中执行以上的代码,结果是:

Python# Python 2.7
>>> import socket
>>> s = socket.socket()
>>> s.connect(('www.baidu.com', 80))
>>> s.sendall('test')

Python 2中执行成功。

Python# Python 3.4
>>> import socket
>>> s = socket.socket()
>>> s.connect(('www.baidu.com', 80))
>>> s.sendall('test')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' does not support the buffer interface

Python 3中却发生了异常。

同样的代码换个环境却不能执行了,我没有写错呀,怒砸电脑。好吧,你确实没写错,是环境变了,导致这个结果的变化请移步官方的说明

接收数据

使用recv函数接收数据:

Pythondata = s.recv(4096)

在Python 3中返回的是bytes对象,在Python 2中返回的是string。注意函数返回的数据长度是小于或者等于参数指定的长度的,要接收到指定长度的数据,需要循环接收数据。

Pythondef myreceive(s, msglen):
    chunks = []
    bytes_recd = 0
    while bytes_recd < msglen:
        chunk = s.recv(min(msglen - bytes_recd, 2048))
        if chunk == b'':
            raise RuntimeError("socket connection broken")
        chunks.append(chunk)
        bytes_recd = bytes_recd + len(chunk)
    return b''.join(chunks)

关闭连接

当连接不再需要时可以使用close关闭socket连接,关闭后的连接不能再进行任何操作。当一个socket被回收时会自动关闭,但是不要依赖这种机制,不需要socket时就主动的close。

服务端

服务端程序执行的步骤:
1. 创建服务端socket
1. 将服务端socket绑定到指定的地址和端口
1. 监听连接
1. 接受客户端连接
1. 处理客户端的数据
1. 关闭客户端连接

一个简单的echo server示例:

Pythonimport socket

HOST = ''
PORT = 10022

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(10)
conn, addr = s.accept()
while True:
    data = conn.recv(1024)
    if not data:
        break
    conn.sendall(data)
conn.close()

客户端程序:

Pythonimport socket

HOST = 'localhost'
PORT = 10022

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'hello socket')
data = s.recv(1024)
print('Received', repr(data))
s.close()

错误处理

socket处理过程中发生错误会抛出异常,socket相关的异常有:
- socket.error
- socket.herror
- socket.gaierror
- socket.timeout

Pythonimport socket

HOST = None
PORT = 10022

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((HOST, PORT))
    s.listen(10)
except: socket.error as msg:
    print(msg)

参考资料

查看原文

赞 3 收藏 19 评论 5

wzyplus 回答了问题 · 2015-04-06

精通java能否给学习python或者其他语言带来便利?

其实可以把两个语言对比着学,比如学了Java的面向对象,可以想想Python中该如何实现,看看两者有什么不同的地方。

关注 11 回答 9

认证与成就

  • 获得 12 次点赞
  • 获得 0 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 0 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2015-04-06
个人主页被 322 人浏览