Resive world

Come world to Record life


  • Home

  • Tags

  • Categories

  • Archives

  • Sitemap

  • Search

python类变量和成员变量的使用注意点

Posted on 2016-09-04 | In Python

之前在用python写一个项目,发现一个很恶心的bug,就是同由一个类生成的两个实例之间的数据竟然会相互影响,这让我非常不解。后来联想到java的类有类变量也有实例变量,因此翻阅了相关资料,发现python也有类似的类变量和实例变量,比如下面的代码中:

1
2
3
4
class A:
x = 0
def __init__(self):
self.y = 0

x就是类变量,y就是实例变量。

原则上是没有错的,但是实际用的时候就发现一些恶心的问题(也就是我找了三天的bug)。。。比如下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A:
x = []
y = 0
def __init__(self):
pass

def add(self):
self.x.append('1')
self.y+=1
a=A()
print a.x,a.y
print A.x,A.y
a.add()
print a.x,a.y
print A.x,A.y
b=A()
print b.x,b.y
print A.x,A.y

这里很明显x和y都是类变量,add的作用是分别对x和y做出修改。然后构造一个实例a,对实例a的值进行修改,最后构造实例b。

本以为这个结果是显而易见的,然而他输出的结果却是:

1
2
3
4
5
6
[] 0
[] 0
['1'] 1
['1'] 0
['1'] 0
['1'] 0

问题在哪?明明x和y都是类变量,在第二组print中为什么a.x和b.x一样,但是a.y和b.y就是不一样呢?

想了半天悟了一个道理。。。就是对于python来说,类变量的确是所有类共有的东西。但是那是在我们用的同一个引用的情况下,比如对于[]对象的append方法就是公用一个类变量了;但是对于赋值语句来说,如果在类中对类变量使用了赋值语句,那么python就会生成一个该对象的副本,以后的操作都是基于这个副本而不会对原来的类对象造成影响。这样就解释的通上面的现象了。

那么为了杜绝自己忘记类变量和实例变量的区别导致本不想公用变量的时候公用了变量,最好的办法就是在每个类中使用变量的时候重新初始化一下,这样就不会导致意外了。

制服火龙——为骁龙810降温

Posted on 2016-08-30 | In 实验室

“高通骁龙 810 是我们的一款失败的产品”——高通工程师

Read more »

如何选择 AOKP 类 ROM 和厂商定制 UI

Posted on 2016-08-29 | In 异闻堂

最近老是被人问及,在厂商提供的原厂 ROM 、AOKP ,和移植的其它ROM(比如移植的 flyme 和 MIUI),到底应该怎么选择。于是我决定写一写这篇博客,从功能层面和国内用户的行为习惯来讲讲如何选择这几类 ROM。

Read more »

MySQL配置远程访问

Posted on 2016-08-27 | In Database

前言

在使用MySQL数据库的时候,有时候需要客户机直接远程登陆服务器的数据库 ,而不是将请求发给数据库服务器。这时候就需要配置下MySQL的远程访问权限了。具体的配置方法也很简单,随便找个搜索引擎基本都能找到搜索到一堆配置MySQL数据库远程登陆的教程了。

步骤

网上介绍的步骤基本分为两步:

修改my.cnf配置文件

mysql的配置文件一般在/etc/mysql/my.cnf 里,打开查看其配置,其中有这么一段:

1
2
3
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1

这个bind-address就是绑定IP,也就是默认只允许本机登陆。为了能够实现远程登陆,显然需要把这句话注释掉。修改完重启mysql服务。

添加用户权限

按照需要,为指定用户、IP设置对应的权限即可

1
2
mysql>GRANT ALL PRIVILEGES ON A.B TO 'user'@'%'IDENTIFIED BY ‘password' WITH GRANT OPTION;
mysql>FLUSH PRIVILEGES

这里把数据库A的B表的所有权限都授予来自任意主机(‘%’)的user以密码’password’登陆。

或者直接修改mysql数据库中的user表使其满足要求。

上面就是理论上需要做的了,然而我照着这个弄完了发现还是连接不上。折腾了半天,终于发现原来服务器的提供商为了保证服务器的安全性,还额外对端口的开放进行了限制。比如腾讯服务器就设置了一个安全组,额外限制了开放的端口,默认是禁止开放mysql的3306端口的,因此要打开控制台,配置好权限:

其他都是默认的,只要额外添加倒数第二行的就行了。。。

参考资料

打开MySQL数据库远程访问的权限
腾讯服务器安全组

 

Apache配置ssl支持https

Posted on 2016-08-27 | In Apache

前言

很明显apache原生是不支持https的,无论是用https访问自身的站点,还是代理来自其他网站的https的站点。毕竟人家https走的端口是443,都不是默认的80。

那么如何让apache支持https呢,其实只要添加下ssl模块再修改下配置就好了。

准备工作

首先要导入apache的ssl模块,即$sudo a2enmod ssl ,保证/etc/apache2/mods-enabled/ 目录下有对应的ssl模块文件。

然后利用openssl命令,生成必要的密钥文件等:

1
2
3
4
5
6
7
8
【生成一个自签名证书】
$ openssl genrsa -out ca.key 2048

【生成证书签名请求(CSR)】
$ openssl req -new -key ca.key -out ca.csr

【生成X509自签名证书】
$ openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt

三条命令各生成三个文件,把这三个文件保存好,这里我把他全部放在了/etc/apache2/key文件夹下了。

配置https正向代理

对于https的正向代理,在http的正向代理配置的基础上,只要额外添加下面的配置即可:

1
2
3
SSLProxyEngine on
SSLCertificateFile /etc/apache2/key/ca.crt
SSLCertificateKeyFile /etc/apache2/key/ca.key

文件路径分别对应上面的密钥文件。

重启服务器即可代理https协议了。

配置https站点

我们知道对于通常的http站点,他的配置路径是在/etc/apache2/sites-enabled/000-default.conf上,但是我发现如果直接在这里配置https站点则会不起效果。一番捣鼓之后发现,其实为了区分http和https站点并加以分别配置,apache2还特地给了另外一份配置文件,这份配置文件的模板需要我们用下面的命令得到:

1
2
3
4
$ sudo a2ensite
Your choices are: 000-default default-ssl
Which site(s) do you want to enable (wildcards ok)?
default-ssl

之后我们就会发现,出现了一个/etc/apache2/sites-enabled/default-ssl.conf文件,没错,我们就可以在这里配置对应的站点了。
在这个配置文件里,主要是要修改四项:

1
2
3
4
DocumentRoot /var/www/html/wordpress
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/cert_chain.crt
SSLCertificateKeyFile /etc/apache2/ssl/private.key

修改好后,重启服务即可。
最后我们可以将利用htaccess文件将80端口的请求转发到443端口,这样更加漂亮。

关于证书

当然,我们自己生成的证书是不被浏览器认可的,通常访问的用户都会被告知这是一个不安全的链接,尤其是chrome,那个红色背景格外的吓人,因此如果是真的想让自己的网站能用https,要么去花钱买证书,要么去用人家免费的,我这里用的是sslforfree的证书,不过麻烦的是这个东西得每隔三个月更换一次。。。
具体的使用方法可以参考这篇文章。

参考资料

CentOS中Apache服务器HTTPS配置方法
Apache + WordPress + SSL 完全指南
申请免费的SSL证书

Apache配置代理服务器

Posted on 2016-08-26 | In Apache

前言

最近在搞爬虫,单机的爬虫如果请求速度过快很容易导致服务器拒绝服务(403),搞不好还可能被封IP,因此通常都需要大量的代理服务器来分散请求的来源,提高爬取效率。网上虽然有些免费的代理IP资源的发布平台,比如国内的西剌免费代理,国外的免费代理列表(需翻墙),这里的代理虽然多,但是毕竟是大家都在用,速度和稳定性都特别差,不到万不得已还是不用为好。因此,比较保险的做法就是自己搞些或者借些服务器,自己搭建代理。当然,这里所说的代理就是“正向代理”了。

鉴于之前一直在弄Apache,这里就用Apache来配置正向代理服务器。

正向代理

所谓”正向代理(forward proxy)“,apache文档里的解释是:

1
2
3
An ordinary <dfn>forward proxy</dfn> is an intermediate server that sits between the client and the _origin server_. In order to get content from the origin server, the client sends a request to the proxy naming the origin server as the target. The proxy then requests the content from the origin server and returns it to the client. The client must be specially configured to use the forward proxy to access other sites.

A typical usage of a forward proxy is to provide Internet access to internal clients that are otherwise restricted by a firewall.

就是用户主动的将自己对目标的请求转发给代理服务器,让代理服务器真正的请求目标,并将结果返回过来。这通常就是用于科学上网、共享网关等讨巧的事了。。。。。

Apache配置

关于Apache的安装和配置文件的简介可以看《apache2服务器的搭建与配置》。

加载模块

配置代理服务器需要用到proxy_http和proxy模块,首先查看/etc/apache2/mods-enabled/ 目录下有没有proxy_http.load proxy.load proxy.conf 这些东西,如果没有,就得先激活下这两个模块:

1
2
$sudo a2enmod proxy_http
$sudo a2enmod proxy

如果显示proxy_http无法激活,就先把本地的proxy.conf删掉,再激活即可。

配置代理

事实上,下面的配置可以写在配置主文件(apache2.conf)包含的任何文件中,但是为了方便管理和区分,我们把代理服务器的配置信息写在/etc/apache2/mods-enabled/proxy.conf里。

打开这个文件,默认内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<IfModule mod_proxy.c>

# If you want to use apache2 as a forward proxy, uncomment the
# 'ProxyRequests On' line and the <Proxy *> block below.
# WARNING: Be careful to restrict access inside the <Proxy *> block.
# Open proxy servers are dangerous both to your network and to the
# Internet at large.
#
# If you only want to use apache2 as a reverse proxy/gateway in
# front of some web application server, you DON'T need
# 'ProxyRequests On'.

#ProxyRequests On
#<Proxy *>
# AddDefaultCharset off
# Require all denied
# #Require local
#</Proxy>

# Enable/disable the handling of HTTP/1.1 "Via:" headers.
# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
# Set to one of: Off | On | Full | Block
#ProxyVia Off

</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

现在我们要对他加以修改,我这里的配置是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<IfModule mod_proxy.c>

# If you want to use apache2 as a forward proxy, uncomment the
# 'ProxyRequests On' line and the <Proxy *> block below.
# WARNING: Be careful to restrict access inside the <Proxy *> block.
# Open proxy servers are dangerous both to your network and to the
# Internet at large.
#
# If you only want to use apache2 as a reverse proxy/gateway in
# front of some web application server, you DON'T need
# 'ProxyRequests On'.

#ProxyRequests On
#<Proxy *>
# AddDefaultCharset off
# Require all denied
# #Require local
#</Proxy>

Listen 1234
<VirtualHost proxy.mythsman.com:1234>
ServerAdmin dqz48548263@qq.com
DocumentRoot /var/www/html/proxy
ServerName proxy.mythsman.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

ProxyRequests On
ProxyVia On

<Proxy *>
Order deny,allow
deny from all
Allow from 115.159.127.117
</Proxy>
</VirtualHost>
# Enable/disable the handling of HTTP/1.1 "Via:" headers.
# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
# Set to one of: Off | On | Full | Block
#ProxyVia Off

</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

这算是综合了网上各种奇奇怪怪的博客到腾出来的能用的配置。

首先要监听端口号,然后创建一个虚拟主机,响应本机的端口,接着开启代理模式,控制入网的IP(先deny 后allow,只允许特定的IP使用代理服务)。

最后重启服务即可。

测试

配置完成后,现在就能代理http协议了(https协议以后再说)。将符合allow条件的主机使用该服务器进行代理,打开网页抓包今后就能发现Remote Address已经变成了代理的IP,而且也多了几个proxy-开头的头信息,这就说明代理已经完成了。

当然也可以用python脚本进行代理测试,代码就不贴了,很简单。

参考资料

StackOverflow——proxy: No protocol handler was valid for the URL
Apache Module mod_proxy

MySQL+python接口更新问题

Posted on 2016-08-23 | In Python

从前用MySQL的python接口一直是可以用的,但是好像是在ubuntu升级到16.04之后import MySQLdb 的时候就会报下面这个错:

1
ImportError: libmysqlclient.so.18: cannot open shared object file: No such file or directory

他说有个库找不到,于是我就在本地用locate 找了找,竟然找到了libmysqlclient.so.20这个东西。。。本地的版本竟然比需求的版本高,这就很纠结了。通常情况下如果这个文件找不到,那我们可以想办法下载这个库;如果版本过低,那就升级更新下就好了;但是现在是版本过高,这时候有不太好换成版本低的。。。

整了好久,终于在stackoverflow里找到了解决办法,就是用pip先卸载MySQL-python然后再安装。。。感觉这个大概就是把MySQL-python升级一下,使他不再依赖老版本,而是依赖新版本的libmysqlclient库。。。也是醉了。

好用的Web包管理器-Bower

Posted on 2016-08-12 | In 环境配置

Bower是twitter推出的客户端包管理工具,用于命令行操作包的搜索、下载、更新、卸载(如jQuery、Bootstrap、JavaScript、HTML、CSS之类的网络资源)。Bower对包结构没有强制规范,可以很方便获取各种Web模块文件,但bower本身不存储模块文件和模块版本信息,模块发布者通过register方式将模块可访问的公开的git地址记录在bower的数据库中,而所有版本都是通过代码库的tag来决定的。

Read more »

PostGIS初探

Posted on 2016-08-04 | In Database

PostGIS是PostgreSQL的空间扩展,他使得PostgreSQL支持空间数据类型,比如点、线段、折线段、多边形、椭圆等等,并且能够使用高效的空间索引进行存储和查找。

安装

ubuntu下在安装好PostgreSQL的基础下用apt install postgis即可。

确认安装版本可以用在postgreSQL的shell里查询:

1
myths=# select * from pg_available_extensions where name like 'postgis%';

我这里大概显示的是:

1
2
3
4
5
6
name          | default_version | installed_version |                               comment                               
------------------------+-----------------+-------------------+---------------------------------------------------------------------
postgis_sfcgal | 2.2.1 | | PostGIS SFCGAL functions
postgis | 2.2.1 | | PostGIS geometry, geography, and raster spatial types and functions
postgis_topology | 2.2.1 | | PostGIS topology spatial types and functions
postgis_tiger_geocoder | 2.2.1 | | PostGIS tiger geocoder and reverse geocoder

很明显可以看见版本和说明。

简要使用

用好这个扩展好像也是个挺麻烦的事的,因为这个牵涉到使用很多的函数,因此查看帮助文档就显得很必要了。

下面就以对点进行最近邻的查找为例。

首先要导入该扩展:

1
>myths=# create extension postgis;

导入后会在数据库里多出下面这几个表:

1
2
3
4
5
6
7
8
9
10
myths=# \d
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+-------
public | geography_columns | view | myths
public | geometry_columns | view | myths
public | raster_columns | view | myths
public | raster_overviews | view | myths
public | spatial_ref_sys | table | myths
(5 rows)

这些东西都是postgis必备的东西,尤其是spatial_ref_sys表,保存了不同的坐标系信息。

然后建表:

1
myths=# create table testTable(id int primary key ,geo geometry(point,0));

基本的sql语句,不同的是geo字段的类型是point,而且后面跟了个数字。这个数字是srid,表示我们使用的坐标集。这个数字对应的是之前的spatial_ref_sys里的字段。通常的经纬度坐标集对应的srid是4326,而这里的0表示我用的是普通的几何坐标。关于srid的问题可以直接百度。

插入语句:

1
myths=# insert into testTable values(1,ST_GeomFromText('POINT(32 66)',0));

这就用到了st_geomfromtext()函数,这个函数把文本形式的类型转换为实际类型,并且指定srid,插入到表中。

对应的类型还有:

1
2
3
4
5
6
7
8
• POINT(0 0)
• LINESTRING(0 0,1 1,1 2)
• POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
• MULTIPOINT(0 0,1 2)
• MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))
• MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))
• GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))
。。。。。。

批量生成数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Random;

public class Test {
public static void main(String[] args) throws IOException {
BufferedWriter writer = Files.newBufferedWriter(Paths.get("/home/myths/Desktop/data.txt"));
Random rand = new Random();
int left = -500000, right = 500000, up = 500000, down = -500000;
int number = 1000000;
writer.write("begin;\n");
for (int i = 0; i < number; i++) {
int randx = rand.nextInt(right - left) + left;
int randy = rand.nextInt(up - down) + down;
String query = String.format("insert into testTable values(%d,ST_GeomFromText('POINT(%d %d)',0));\n", i,
randx, randy);
writer.write(query);
}
writer.write("commit;\n");
writer.flush();
writer.close();
System.out.println("done");
}
}

生成后用myths=# \i ~/Desktop/data.txt导入即可。

最近邻查找
myths=# select id,st_astext(geo) from testtable order by geo<->st_geomfromtext('point(10 10)',0) limit 10;
这个语句就是查找距离点(10,10)最近的前10个点。这里<->表示求距离,st_astext()函数把wkb形式的数据转换成wkt的可读形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
id   |     st_astext     
--------+-------------------
863823 | POINT(-388 537)
789164 | POINT(-136 -947)
841388 | POINT(670 808)
368903 | POINT(1069 664)
169180 | POINT(1209 -458)
359475 | POINT(-83 1348)
167871 | POINT(792 -1300)
337646 | POINT(-1047 1152)
585595 | POINT(-955 1439)
46949 | POINT(-920 -1480)
(10 rows)

Time: 2207.639 ms

否则就是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
myths=# select id,geo from testtable order by geo<->st_geomfromtext('point(10 10)',0) limit 10;
id | geo
--------+--------------------------------------------
863823 | 010100000000000000004078C00000000000C88040
789164 | 010100000000000000000061C00000000000988DC0
841388 | 01010000000000000000F084400000000000408940
368903 | 01010000000000000000B490400000000000C08440
169180 | 01010000000000000000E492400000000000A07CC0
359475 | 01010000000000000000C054C00000000000109540
167871 | 01010000000000000000C0884000000000005094C0
337646 | 010100000000000000005C90C00000000000009240
585595 | 01010000000000000000D88DC000000000007C9640
46949 | 01010000000000000000C08CC000000000002097C0
(10 rows)

Time: 690.557 ms

添加索引
myths=# create index testIndex on testtable using gist(geo);
对于空间类型添加的索引是gist类型的,具体含义参见文档。

添加了索引后可以发现查询效率有明显提升:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
myths=# select id,st_astext(geo) from testtable order by geo<->st_geomfromtext('point(10 10)',0) limit 10;
id | st_astext
--------+-------------------
863823 | POINT(-388 537)
789164 | POINT(-136 -947)
841388 | POINT(670 808)
368903 | POINT(1069 664)
169180 | POINT(1209 -458)
359475 | POINT(-83 1348)
167871 | POINT(792 -1300)
337646 | POINT(-1047 1152)
585595 | POINT(-955 1439)
46949 | POINT(-920 -1480)
(10 rows)

Time: 49.153 ms

myths=# select id,geo from testtable order by geo<->st_geomfromtext('point(10 10)',0) limit 10;
id | geo
--------+--------------------------------------------
863823 | 010100000000000000004078C00000000000C88040
789164 | 010100000000000000000061C00000000000988DC0
841388 | 01010000000000000000F084400000000000408940
368903 | 01010000000000000000B490400000000000C08440
169180 | 01010000000000000000E492400000000000A07CC0
359475 | 01010000000000000000C054C00000000000109540
167871 | 01010000000000000000C0884000000000005094C0
337646 | 010100000000000000005C90C00000000000009240
585595 | 01010000000000000000D88DC000000000007C9640
46949 | 01010000000000000000C08CC000000000002097C0
(10 rows)

Time: 1.092 ms

参考

PostGIS.net
PostGIS 2.0 Manual
PostGIS 在 O2O应用中的优势

PostgreSQL安装使用

Posted on 2016-08-04 | In Database

PostgreSQL大概是除MySQL之外的最好用的开源数据库管理系统了,有着开源数据库中最好的空间扩展,当前的应用也特别的多。当然我主要就是冲着PostGIS来的,不过在这之前首先得会玩PostGreSQL。下面就简要记录下使用过程。

安装

PostgreSQL有个官方网站,这里有简要的说明和文档。ubuntu下安装直接用apt大法就可以。这里需要注意下版本,不要在电脑里留多个不同的版本。

安装好后在shell里用$psql -V来查看版本。在\etc\postgresql\ 目录下也会有对应版本号的配置文件。如果发现什么端口错误或者被占用的问题可以在postgresql.conf下修改下端口或者删除多余的版本。

使用

PostgreSQL和其他数据库有个很大的不同就是他登陆的时候是以数据库的身份登陆的,默认的数据库是postgres(而且会在安装时自动生成postgres这个角色)。因此我们首先得以postgres的角色进行操作。

具体的创建角色和数据库的过程参照**PostgreSQL学习手册(角色和权限)**。

关于其他的细节可以参考**PostgreSQL 8.1 中文文档**这里的教程来。

说明

  1. 一般的SQL语句与其他类型的数据库差不多。
  2. 选择数据库、选择表等操作可以用\?命令查看,比如\d  \l  \timing 等。
  3. 一些内置的表基本都是以pg_ 开头,而且可以用自动补全来查看,比如管理角色的pg_roles 表、管理密码的pg_shadow 表等。

参考

PostgreSQL学习手册(角色和权限)
PostgreSQL 8.1 中文文档

1…394041…58

574 posts
69 categories
286 tags
© 2024 Companyd
Powered by Hexo
|
Theme — NexT.Muse v5.1.4