LittleQ

爱好:写代码

平时做数据分析统计跑程序脚本需呀经常用到各种时间的转化和传入,日期的格式化,日期的相减,字符串时间互转。每次都是现查,比较浪费时间,这里把平时常用到的总结一下,因为涉及到好几个脚本语言的时间函数,我也记不住,干脆整理出一个查表更方便。主要涉及到Shell,Python,MySQL,Hive这几个脚本

Shell

Shell感觉是最生涩的,最恶心的就是空格不能多也不能少,也没个IDE命令提示啥的,用的也最少,所以老容易忘

  • 常用的几种用法
1
2
3
4
5
6
7
8
$ date	以默认格式显示当前日期(Fri Nov 18 10:38:07 CST 2011)
$ date +%Y%m%d 以yyyymmdd格式输出(20160423)
$ date +"%Y%m%d %A" 以"yyyymmdd 星期"格式输出(20160423 Friday)
$ date -d "1 day" +%Y%m%d 显示一天后的日期(20160424)
$ date -d "3 day ago" +%Y-%m-%d 以指定格式显示3天前的日期(2016-04-26)
$ date -d "1 month" +%Y-%m-%d 以指定格式显示一个月后的日期
$ date -d "1 month" +%s 以指定格式显示一个月后的日期的秒数,%S为当前的秒数(0~59)
$ date -d "1970-01-01 CST 1 second" +%s 显示从1970-01-01 CST起1秒后的秒数
  • -d这个参数可以产生各种时间组合
1
2
3
4
$ date -d "-2 day 20160423" +%Y%m%d
20160421
$ date -d "+7 day 20160423" +%Y%m%d
20160430
  • 日期循环

这个场景还是很常用的,一般脚本都是默认跑当天或者前一天的数据,如果要一次重跑每一天的数据,可能就需要用到Shell日期循环:

1
2
3
4
5
6
7
8
begin_date='20160401'
end_date='20160423'

while [ "$begin_date" != "$end_date" ]
do
echo $begin_date
begin_date=`date -d "1 day $begin_date" +%Y%m%d`
done

**注意:**一定要用""把条件扩起来,!=史比较字符串的。

Python

Python里用的比较多的就是两个包datetime,time

  • datetime
1
2
3
4
5
6
7
8
9
datetime.datetime.now().strftime('%Y-%m-%d')	# 2016-04-23
str(datetime.datetime.now())[:10] # 2016-04-23
(datetime.datetime.now() + datetime.timedelta(days=-1)).strftime('%Y-%m-%d') # 2016-04-22
datetime.datetime.strptime('2016-04-23', '%Y-%m-%d') # 将字符串格式为datetime对象
(d1 - d2 ).days # d1,d2 为datetime对象,计算连个日期之间相差多少天
(d1 - d2 ).seconds # d1,d2 为datetime对象,计算连个日期之间相差多少秒
datetime.weekday() # 返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推;
datatime.isoweekday() # 返回weekday,如果是星期一,返回1;如果是星期2,返回2,以此类推;
datetime.fromtimestamp(timestamp) # 根据给定的时间戮,返回一个datetime对象;
  • time
    1
    time.strftime('%Y-%m-%d %H:%M:%S') # 格式化输出当前时间

MySQL

主要是一些时间转换函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> select unix_timestamp('2016-01-01 10:10:10');
+---------------------------------------+
| unix_timestamp('2016-01-01 10:10:10') |
+---------------------------------------+
| 1451614210 |
+---------------------------------------+
1 row in set (0.01 sec)

mysql> select from_unixtime(unix_timestamp());
+---------------------------------+
| from_unixtime(unix_timestamp()) |
+---------------------------------+
| 2016-06-18 13:07:53 |
+---------------------------------+
1 row in set (0.00 sec)

Hive

1
2
3
to_date('2016-04-23')	# 2016-04-23
to_date('2016-04-23 12:21:10') # 2016-04-23
datediff(end_time, start_time) # 返回日期相隔天数

一时手贱把~/tmp/文件夹删了,结果火狐打不开了,最后在网上找了很久才找到解决方案,记录一下防止下次手贱了。
大部分文章只提到,把~/.mozilla文件的权限更改成当前用户和用户组,就可以了:

  • 察看.mozilla文件件的权限属性
1
$ ls -l

如果~/.mozilla文件夹的属性是root则改变文件夹的属性为当前用户。命令如下:

  • 需改文件夹权限
1
$ sudo chown -hR zhangsan:zhangsan ~/.mozilla/

如此操作后,其实firefox还是启动不了,因为,还有一个文件夹的属性仍然是root,这个文件夹就是~/.cache/mozilla

1
2
3
$ cd ~/.cache
$ ls -l
$ sudo chown -hR zhangsan:zhangsan mozilla/

经过如此折腾,双击firefox图标,才能正常启动firefox浏览器。
太坑爹了。

有时候在统计的时候,需要把包含中文的列过滤掉,主要是存在历史脏数据,比如我们的客户端存在新老客户端之分,日志记录不一样,所有有些活动或者名字在pv,uv的时候不一致,例如活动的名字一般就算有英文也不可能全是英文,所以我们在计算的时候,需要把全为英文的过滤掉:

1
where LENGTH(`col_name`) <> CHARACTER_LENGTH(`col_name`) 

这里的col_name是mysql里表的列名

有时候为了测试,需要单独建一些MySQL用户来限定这部分用户的权限,并且需要限定哪些ip可以访问到我的数据库,具体步骤为,在装有MysQL的机器上执行:

  1. 创建用户,一般为了避免暴露自己的密码习惯,可以用Linux自带的生成密码命令
1
2
➜✗ md5pass
$1$6Fy9BTnB$Ruw50OR1oiUCwP73abnlD0

备注:6Fy9BTnB为用户名,Ruw50OR1oiUCwP73abnlD0为密码
然后执行MySQL命令,语法为:

1
mysql> CREATE USER 'username'@'host' IDENTIFIED BY 'password';

假设你机器IP为192.168.1.101,则对应的命令为:

1
CREATE USER '6Fy9BTnB'@'Ruw50OR1oiUCwP73abnlD0' IDENTIFIED BY '192.168.1.101';
  1. 给MySQL用户附权限
1
mysql> grant 权限1,权限2,...权限n on 数据库名称.表名称 to 用户名@用户地址 identified by 'password';

例如:

1
mysql>grant select,insert,update,delete,create,drop on order.oerder_info to 6Fy9BTnB@192.168.1.101 identified by 'Ruw50OR1oiUCwP73abnlD0';

只有来自192.168.1.101的用户6Fy9BTnB才能有对应的访问权限,其他的机器是无法访问的。
这里还有个快捷的操作,如果要附所有表的的所有操作权限,不可能一个一个去写,命令如下:

1
mysql>grant all privileges on order.oerder_info to 6Fy9BTnB@192.168.1.101 identified by 'Ruw50OR1oiUCwP73abnlD0';

最初源于一个错误,在使用python包sqlalchemy执行sql统计的时候,报错:

This result object is closed sqlalchemy

网上查阅了一下,貌似是多个线程共同使用一个会话或者连接导致,由于之前在其他机器上使用的1.0.8版本同样的sql都没有报过错,我直接用yum安装的0.7.x版本,可能是这个版本比较老,于是我想重新使用pip安装最新版,由于之前升级python,pip是我编译安装的最新版,CentOS自带的是1.4.x版本,我安装的是7.1.2,所以才会有下面的各种问题。

1
sudo pip install sqlalchemy

报错:

Requirement already satisfied (use –upgrade to upgrade): sqlalchemy in /home/q/python27/lib/python2.7/site-packages
You are using pip version 7.1.2, however version 8.0.2 is available.
You should consider upgrading via the ‘pip install –upgrade pip’ command.

于是加上建议重新安装:

1
sudo pip install --upgrade sqlalchemy

仍然报错:

The repository located at pypi.xxx.xxx.com is not a trusted or secure host and is being ignored. If this repository is available via HTTPS it is recommended to use HTTPS instead, otherwise you may silence this warning and allow it anyways with ‘–trusted-host pypi.abc.def.com’.

依然按照建议加上参数:

1
sudo pip install --trusted-host pypi.abc.def.com --upgrade sqlalchemy

然后就安装成功了。

有时候升级pip会报这个错:

1
The pip==7.1.0' distribution was not found and is required by the application

详细解决方案如下:

1
2
3
4
5
6
7
8
9
10
11
[root@xxx ~]# easy_install pip
Searching for pip
Best match: pip 9.0.1
Adding pip 9.0.1 to easy-install.pth file
Installing pip script to /usr/local/python2.7/bin
Installing pip3.5 script to /usr/local/python2.7/bin
Installing pip3 script to /usr/local/python2.7/bin

Using /usr/local/python2.7/lib/python2.7/site-packages
Processing dependencies for pip
Finished processing dependencies for pip

然后看看系统的pip是哪个地方:

1
2
[root@xxx ~]# which pip
/usr/bin/pip

然后我们需要编辑一下这个文件vi /usr/bin/pip:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==7.1.0','console_scripts','pip'
__requires__ = 'pip==9.0.1'
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
sys.exit(
load_entry_point('pip==9.0.1', 'console_scripts', 'pip')()
)

就是把pip改成你系统安装的pip,然后就可以安装包了.

在使用matplotlib画图的时候,出现了以下错误:

/home/q/python27/lib/python2.7/site-packages/matplotlib-1.5.1-py2.7-linux-x86_64.egg/matplotlib/font_manager.py:1288: UserWarning: findfont: Font family [u’sans-serif’] not found. Falling back to Bitstream Vera Sans
(prop.get_family(), self.defaultFamily[fontext]))

这让我十分费解,应该有这个字体的,于是让其他人登陆跑同样的程序则可以运行,于是我好奇登陆了交互式环境,引入matplotlib包看了一下,结果出现以下错误:

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
Python 2.7.4 (default, Dec 24 2013, 16:30:42)
[GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/q/python27/lib/python2.7/site-packages/matplotlib-1.5.1-py2.7-linux-x86_64.egg/matplotlib/__init__.py", line 111, in <module>
import inspect
File "/home/q/python27/lib/python2.7/inspect.py", line 42, in <module>
from collections import namedtuple
File "collections.py", line 17, in <module>
import numpy as np
File "/home/q/python27/lib/python2.7/site-packages/numpy-1.10.4-py2.7-linux-x86_64.egg/numpy/__init__.py", line 180, in <module>
from . import add_newdocs
File "/home/q/python27/lib/python2.7/site-packages/numpy-1.10.4-py2.7-linux-x86_64.egg/numpy/add_newdocs.py", line 13, in <module>
from numpy.lib import add_newdoc
File "/home/q/python27/lib/python2.7/site-packages/numpy-1.10.4-py2.7-linux-x86_64.egg/numpy/lib/__init__.py", line 8, in <module>
from .type_check import *
File "/home/q/python27/lib/python2.7/site-packages/numpy-1.10.4-py2.7-linux-x86_64.egg/numpy/lib/type_check.py", line 11, in <module>
import numpy.core.numeric as _nx
File "/home/q/python27/lib/python2.7/site-packages/numpy-1.10.4-py2.7-linux-x86_64.egg/numpy/core/__init__.py", line 58, in <module>
from numpy.testing import Tester
File "/home/q/python27/lib/python2.7/site-packages/numpy-1.10.4-py2.7-linux-x86_64.egg/numpy/testing/__init__.py", line 10, in <module>
from unittest import TestCase
File "/home/q/python27/lib/python2.7/unittest/__init__.py", line 58, in <module>
from .result import TestResult
File "/home/q/python27/lib/python2.7/unittest/result.py", line 9, in <module>

这个时候就很郁闷了,服务器上的matplotlib都是我装的,结果反倒我不能用,但是后来在网上看到了解决方案:原来出现这个问题是由于用户目录下的缓存导致的,需要清空缓存:

1
sudo rm -r ~/.cache/

清空缓存之后就可以运行了。

写了个脚本读取指定文件的某一行到某一行,然后利用行数据做一些匹配提取,在终端中调用方式为:

1
python run.py file_name beg_line end_line

代码如下:

1
2
3
4
5
6
7
8
if __name__ == '__main__':
file_name = sys.argv[1]
beg_line = sys.argv[2]
end_line = sys.argv[3]

with open(file_name, 'rb') as f:
for val in f.readlines()[beg_line:end_line]:
print val.strip()

当我在终端中输入:

1
python run.py 12 20

时,报错:

TypeError: slice indices must be integers or None or have an index method

解决办法,python作为一个解释型语言,对类型没有强制检查,我们虽然输入的是两个数字,但是实际上beg_line,end_linestr类型,所以传入切片的类型不对,就会报上面的错。

经常使用github的人应该不陌生,大多数人使用都是先在github的网站上建一个仓库,然后拷贝ssh或者http的地址,然后使用git clone命令来初始化项目,这样比较麻烦,其实可以直接通过命令行的方式来在github上建立一个仓库,然后直接把本地项目推送到github上的。

命令行建立仓库

  1. 认证用户发一个POST就可以新建,于是使用curl构造POST,没有的自己安装:
    1
    curl -u 'username' https://api.github.com/user/repos -d '{"name":"RepoName"}'
  2. 然后把刚才建的仓库的地址加到git配置里
    1
    git remote add origin git@github.com:username/RepoName.git
  3. 推送到github
    1
    git push -u origin master

**注意:**username换成你在github上的注册名,RepoName就是你打算在github上建立的仓库名,注意不要替换user

通过这几步就可以在命令行里完成所有的操作。

Python在涉及到跨包的模块引用的时候,并不像Java这种语言那样,可以做到自动查找包路径。在网上也看到各种说法,有些还是不行,所以打算亲自实验一番。

准备工作

实验环境:

OS:Ubuntu
Python: Python 2.7.10+
IDE:PyCharm

实验之前还要说一下,Python里面,必须在每个文件夹下面建一个__init__.py,这个文件是空的,但是必须要有这个文件,Python才会把这个文件夹视为一个Python Package,包里面的文件就可以称为模块。
首先看看测试工程的目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  package_ref  tree
.
├── module1
│   ├── __init__.py
│   ├── m11.py
│   ├── m12.py
│   └── module11
│   ├── __init__.py
│   └── m1_m11.py
├── module2
│   ├── __init__.py
│   └── m21.py
├── module3
│   ├── __init__.py
│   └── m31.py
└── m.py

具体的引用关系为:

  1. m21.py引用了m11,m12中的函数
  2. m31引用了m1_11中的函数
  3. m.py引用了m11,m12中的函数

文件内容

  • m11.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python
    # coding=utf-8


    def func1():
    print 'm11 func1'


    def func2():
    print 'm11 func2'
  • m12.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python
    # coding=utf-8


    def func1():
    print 'm12 func1'


    def func2():
    print 'm12 func2'
  • m1_m11.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python
    # coding=utf-8


    def func1():
    print 'm1_m11 func1'


    def func2():
    print 'm1_m11 func2'
  • m21.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/usr/bin/env python
    # coding=utf-8
    from module1 import m11, m12


    def func1():
    m11.func1()
    print 'm21 func1'


    def func2():
    m12.func2()
    print 'm21 func2'


    if __name__ == '__main__':
    func1()
    func2()
  • m31.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/usr/bin/env python
    # coding=utf-8
    from module1.module11 import m1_m11


    def func1():
    m1_m11.func1()
    print 'm31 func1'


    def func2():
    m1_m11.func2()
    print 'm31 func2'


    if __name__ == '__main__':
    func1()
    func2()
  • m.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/usr/bin/env python
    # coding=utf-8
    from module1 import m11, m12


    def func1():
    m11.func1()
    print 'm func1'


    def func2():
    m12.func2()
    print 'm func2'

    if __name__ == '__main__':
    func1()
    func2()

执行脚本

在PyCharm里执行,全部都可以正确执行,进入package_ref根目录,终端中执行python m.py,也没有问题。
进入module2目录,执行python m21.py,报错:

Traceback (most recent call last):
File “module2/m21.py”, line 3, in
from module1 import m11, m12
ImportError: No module named module1

进入module3也是同样的错误。

解决方案

在报错的文件中,引入本地包里面的模块之前,头部加上:

1
2
import sys
sys.path.append('..')

其他地方不用改变,测试之后在pyCharm和终端中执行都没有问题。

**备注:**详细的工程在github上也有,git地址为python-package_ref

Ubuntu 14.04设置wifi热点这篇文章中我们使用create_ap来在Ubuntu上建立wifi,主要是看中了它可以建立隐藏wifi的功能,但是在使用的时候老是出问题,例如

WARN: Your adapter does not fully support AP virtual interface, enabling –no-virt
Config dir: /tmp/create_ap.wlan0.conf.A912iinp
PID: 20324
command failed: Operation not supported (-95)
Access Point’s SSID is hidden!
RTNETLINK answers: Operation not possible due to RF-kill

解决办法:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo rfkill list all
0: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
1: dell-wifi: Wireless LAN
Soft blocked: yes
Hard blocked: no
2: dell-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
3: phy0: Wireless LAN
Soft blocked: yes
Hard blocked: no

注意看1和3的Soft blocked那里都是yes,在终端里输入:

1
2
$ sudo rfkill unblock wifi
$ sudo rfkill unblock all

然后再看看

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo rfkill list
0: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
1: dell-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
2: dell-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
3: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no

yes那里变成no了,然后就可以再次使用create_ap来建立wifi了。引用子stackoverflow上网友的原话:

Soft-blocking
The output to sudo rfkill list shows that your network card is “soft-blocked”.
This could happen when the wireless card has been signalled to switch-off via the kernel.
Try the following steps:
run in a terminal:
sudo rfkill unblock wifi; sudo rfkill unblock all
rerun sudo rfkill list to confirm that the card has been unblocked.
reboot
rerun sudo rfkill list again to confirm unblocking as been retained.
rerun sudo lshw -class network - you should now see that the kernel has recognised (or not) the wireless card.
If the wireless kernel module has been recognised (it should not say “unclaimed”), Network Manager should now be able to see wireless networks that are available in your vacinity.

0%