2017年7月

首页2017年7月
26
Jul
0

postgres的json处理 上

只整理了几个常用用法 jsonb也未尝试

--判断表是否存在
select count(*) from pg_class where relname = 'familis_j'
--删除表
drop table IF EXISTS familis_j
--建表
 create table IF NOT EXISTS familis_j(id serial primary key,profile json)
--清除所有记录
truncate table familis_j
--插入数据
insert into familis_j(profile)values('
 {
    "root": {
        "root": "100mb", 
        "home": "200mb", 
        "data": "600mb"
    }, 
    "total": "1000mb", 
    "data": [
        "this is one", 
        "this is two", 
        "this is three"
    ], 
    "iteams": [
        {
            "item": {
                "key1": "value1", 
                "key2": "value2"
            }
        }, 
        {
            "item": {
                "key3": "value3", 
                "key4": "value4"
            }
        }
    ]
}
 ')

--取单层KEY值
select json_extract_path(profile,'root') from familis_j
select json_extract_path_text(profile,'root') from familis_j
--此两行区别 ->>(json_extract_path)返回是json ->()返回文本
select profile ->>'root' as rootValue from familis_j
select profile ->'root'as rootValue from familis_j
--取多层KEY值
select json_extract_path(json_extract_path(profile,'root'),'data') from familis_j

--取数组值
select json_array_elements(json_extract_path(profile,'data')) as json_arr from familis_j

--取item子明细  #>> json  #> 文本
select json_array_elements(json_extract_path(profile,'iteams')) #>> '{item}' from familis_j
select json_array_elements(json_extract_path(profile,'iteams')) #> '{item}' from familis_j

--取节点数量
select json_array_length(json_extract_path(profile,'iteams')) from familis_j

--取items
select profile #> '{iteams}'  from familis_j      --json
select profile #>> '{iteams}'  from familis_j     --文本
select profile ->> 'iteams'  from familis_j       --文本

--取下标为0的item整组数据
select profile #> '{iteams}' -> 0  from familis_j 
--取下标为0的item内的数据
select profile #> '{iteams}' -> 0 #>> '{item}' from familis_j 
--取下标为0的item内key1的数据
select profile #> '{iteams}' -> 0 #> '{item,key1}' from familis_j     --json
select profile #> '{iteams}' -> 0 #>> '{item,key1}' from familis_j    --文本 
25
Jul
0

退出程序(自己)的方法

  1. sys.exit()
    执行该语句会直接退出程序,这也是经常使用的方法,也不需要考虑平台等因素的影响,一般是退出Python程序的首选方法.

该方法中包含一个参数status,默认为0,表示正常退出,也可以为1,表示异常退出.
import sys
sys.exit()
sys.exit(0)
sys.exit(1)
该方法引发的是一个SystemExit异常(这是唯一一个不会被认为是错误的异常),当没有设置捕获这个异常将会直接退出程序执行,当然也可以捕获这个异常进行一些其他操作.

  1. os._exit()
    效果也是直接退出,不会抛出异常,但是其使用会受到平台的限制,但我们常用的Win32平台和基于UNIX的平台不会有所影响。

知乎上有说是调用了C 语言的 _exit() 函数.

  1. os.kill()
    一般用于直接Kill掉进程,但是只能在UNIX平台上有效。

基本原理:该函数是模拟传统的UNIX函数发信号给进程,其中包含两个参数:一个是进程名,即所要接收信号的进程;一个是所要进行的操作。
操作(第二个参数)的常用取值为:
SIGINT 终止进程 中断进程
SIGTERM 终止进程 软件终止信号
SIGKILL 终止进程 杀死进程
SIGALRM 闹钟信号
例如:
os.kill(multiprocessing.current_process().pid,signal.SIGINT)

  1. Windows下Kill进程
    这里使用的是os.popen(), 该方法是用于直接执行系统命令,而在Windows下其实就是使用taskkill来kill掉进程,其基本形式是,

taskkill /pid 程序的PID号码

可以直接在CMD窗口下试下这个命令....

可以先打开一个计算器程序,然后使用tasklist查看该程序的pid,这里是711

import os
if __name__ == "__main__":
     pid = 711
     os.popen('taskkill.exe /pid:'+str(pid))
25
Jul
0

signal信号处理

在了解了Linux的信号基础之 后,Python标准库中的signal包就很容易学习和理解。signal包负责在Python程序内部处理信号,典型的操作包括预设信号处理函数,暂 停并等待信号,以及定时发出SIGALRM等。要注意,signal包主要是针对UNIX平台(比如Linux, MAC OS),而Windows内核中由于对信号机制的支持不充分,所以在Windows上的Python不能发挥信号系统的功能。
  信号(signal)-- 进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。
定义信号名
signal包定义了各个信号名及其对应的整数,比如:
import signal
print(signal.SIGABRT)
print(signal.SIG_DFL)
Python所用的信号名与Linux一致,可以通过$ man 7 signal 查询
预设信号处理函数
signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,如下所示:
singnal.signal(signalnum, handler)
signalnum为某个信号,handler为该信号的处理函数。我们在信号基础里提到,进程可以无视信号,可以采取默认操作,还可以自定义操作。当handler为signal.SIG_IGN时,信号被无视(ignore)。当handler为singal.SIG_DFL,进程采取默认操作(default)。当handler为一个函数名时,进程采取函数中定义的操作。

import signal

Define signal handler function

def myHandler(signum, frame):

print('I received: ', signum)

register signal.SIGTSTP's handler

signal.signal(signal.SIGTSTP, myHandler)
signal.pause()
print('End of Signal Demo')

  在主程序中,我们首先使用signal.signal()函数来预设信号处理函数。然后我们执行signal.pause()来让该进程暂停以等待信号, 以等待信号。当信号SIGUSR1被传递给该进程时,进程从暂停中恢复,并根据预设,执行SIGTSTP的信号处理函数myHandler()。 myHandler的两个参数一个用来识别信号(signum),另一个用来获得信号发生时,进程栈的状况(stack frame)。这两个参数都是由signal.singnal()函数来传递的。

上面的程序可以保存在一个文件中(比如test.py)。我们使用如下方法运行:
$python test.py
以便让进程运行。当程序运行到signal.pause()的时候,进程暂停并等待信号。此时,通过按下CTRL+Z向该进程发送SIGTSTP信号。我们可以看到,进程执行了myHandle()函数, 随后返回主程序,继续执行。(当然,也可以用$ps查询process ID, 再使用$kill来发出信号。)

(进程并不一定要使用signal.pause()暂停以等待信号,它也可以在进行工作中接受信号,比如将上面的signal.pause()改为一个需要长时间工作的循环。)

我们可以根据自己的需要更改myHandler()中的操作,以针对不同的信号实现个性化的处理。

定时发出SIGALRM信号
一个有用的函数是signal.alarm(),它被用于在一定时间之后,向进程自身发送SIGALRM信号:
import signal

Define signal handler function

def myHandler(signum, frame):

print("Now, it's the time")
exit()

register signal.SIGALRM's handler

signal.signal(signal.SIGALRM, myHandler)
signal.alarm(5)
while True:

print('not yet')

  我们这里用了一个无限循环以便让进程持续运行。在signal.alarm()执行5秒之后,进程将向自己发出SIGALRM信号,随后,信号处理函数myHandler开始执行。

发送信号
signal包的核心是设置信号处理函数。除了signal.alarm()向自身发送信号之外,并没有其他发送信号的功能。但在os包中,有类似于linux的kill命令的函数,分别为
os.kill(pid, sid)
os.killpg(pgid, sid)
分别向进程和进程组(见Linux进程关系)发送信号。sid为信号所对应的整数或者singal.SIG*。

实际上signal, pause,kill和alarm都是Linux应用编程中常见的C库函数,在这里,我们只不过是用Python语言来实现了一下。实际上,Python 的解释器是使用C语言来编写的,所以有此相似性也并不意外。此外,在Python 3.4中,signal包被增强,信号阻塞等功能被加入到该包中。我们暂时不深入到该包中。
总结

signal.SIG*

signal.signal()

signal.pause()

signal.alarm()

ps.

信号 取值 默认动作 含义(发出信号的原因)
SIGHUP 1 Term 终端的挂断或进程死亡
SIGINT 2 Term 来自键盘的中断信号
SIGQUIT 3 Core 来自键盘的离开信号
SIGILL 4 Core 非法指令
SIGABRT 6 Core 来自abort的异常信号
SIGFPE 8 Core 浮点例外
SIGKILL 9 Term 杀死
SIGSEGV 11 Core 段非法错误(内存引用无效)
SIGPIPE 13 Term 管道损坏:向一个没有读进程的管道写数据
SIGALRM 14 Term 来自alarm的计时器到时信号
SIGTERM 15 Term 终止
SIGUSR1 30,10,16 Term 用户自定义信号1
SIGUSR2 31,12,17 Term 用户自定义信号2
SIGCHLD 20,17,18 Ign 子进程停止或终止
SIGCONT 19,18,25 Cont 如果停止,继续执行
SIGSTOP 17,19,23 Stop 非来自终端的停止信号
SIGTSTP 18,20,24 Stop 来自终端的停止信号
SIGTTIN 21,21,26 Stop 后台进程读终端
SIGTTOU 22,22,27 Stop 后台进程写终端
 

 
SIGBUS 10,7,10 Core 总线错误(内存访问错误)
SIGPOLL
Term Pollable事件发生(Sys V),与SIGIO同义
SIGPROF 27,27,29 Term 统计分布图用计时器到时
SIGSYS 12,-,12 Core 非法系统调用(SVr4)
SIGTRAP 5 Core 跟踪/断点自陷
SIGURG 16,23,21 Ign socket紧急信号(4.2BSD)
SIGVTALRM 26,26,28 Term 虚拟计时器到时(4.2BSD)
SIGXCPU 24,24,30 Core 超过CPU时限(4.2BSD)
SIGXFSZ 25,25,31 Core 超过文件长度限制(4.2BSD)
 

 
SIGIOT 6 Core IOT自陷,与SIGABRT同义
SIGEMT 7,-,7
Term
SIGSTKFLT -,16,- Term 协处理器堆栈错误(不使用)
SIGIO 23,29,22 Term 描述符上可以进行I/O操作
SIGCLD -,-,18 Ign 与SIGCHLD同义
SIGPWR 29,30,19 Term 电力故障(System V)
SIGINFO 29,-,-
与SIGPWR同义
SIGLOST -,-,- Term 文件锁丢失
SIGWINCH 28,28,20 Ign 窗口大小改变(4.3BSD, Sun)
SIGUNUSED -,31,- Term 未使用信号(will be SIGSYS)

20
Jul
0

FastDFS API的python客户端

网上教程一般都是指python2.7
在3.6下跑不了

主要的坑是pip install fdfs-client-py
安装好之后 代码其实是2.7的 用2to3脚本执行后也是完全不能跑

安装之前,先装mutagen
pip3 install mutagen

所以必须用源码安装
git址址:
https://github.com/jefforeilly/fdfs_client-py.git

测试代码

from fdfs_client.client import *
client_file = '/root/work/testing-platform-execute/Conf/fast_client.conf'
test_file = '/root/work/testing-platform-execute/Conf/fast_client.conf'
download_file = 'test2.txt'

client = Fdfs_client(client_file)
# 上传
ret_upload = client.upload_by_filename(test_file)
print(ret_upload)
time.sleep(5)  # 等待5s,否则下载时会报错文件不存在
file_id = ret_upload['Remote file_id'].replace('\\', '/')  # 新版本文件存放Remote file_id格式变化

# 下载
ret_download = client.download_to_file(download_file, file_id)
print(ret_download)

# 删除
ret_delete = client.delete_file(file_id)
print(ret_delete)

遇到错误ImportError: No module named sendfile
需要到源码fdfs_client/storage_client.py里注释fast_client.rar

from fdfs_client.sendfile import * 这行

配置文件,附件
http://www.zifuchuan.com/me/usr/uploads/2017/07/2056988328.rar

12
Jul
0

sqlalchemy,psycopg2操作postgres的ORM

1.定义连接器及子类

from Common.Config import configer
import sqlalchemy as sqla
import sqlalchemy.orm as sqlorm
from sqlalchemy.ext.declarative import declarative_base as sqla_declarative_base

class PostgresConnection(object):
    session = None
    base = None
    def __init__(self):
        self.base = sqla_declarative_base()
        #engine = sqla.create_engine ('postgresql://postgres:postgres@10.200.163.233:5432/myTest', echo=True,pool_size=10)
        engineStr = ('postgresql://' +
                                      configer.Database['username'] +
                                      ':' +
                                      configer.Database['password'] +
                                      '@' +
                                      configer.Database['serverip'] +
                                      ':' +
                                      configer.Database['port'] +
                                      '/' +
                                      configer.Database['dbname'])
        self.engine = sqla.create_engine(engineStr,
                                     echo=bool(configer.Database['isecho']),
                                     pool_size=int(configer.Database['poolcount']))
        self.base.metadata.bind = self.engine
        self.session = sqlorm.scoped_session(sqlorm.sessionmaker(bind=self.engine))
connection = PostgresConnection()

2.类定义 外键参数定义

from Common.Connection import connection
import sqlalchemy as db
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, backref

class Orders(connection.base):
    __tablename__ = 'orders'
    id = db.Column('id', db.Integer, primary_key=True, autoincrement=True)
    orderid = db.Column('orderid',db.String(20),unique=True,nullable=False)
    name = db.Column('name',db.String(20))

class Details(connection.base):
    __tablename__ = 'details'
    id = db.Column('id', db.Integer, primary_key=True, autoincrement=True)
    detailname = db.Column('detailname',db.String(20))
    #CASCADE 级联更新,DELETE 删除  RESTRICT 不允许对主表纪录操作  外键操作
    orderid = db.Column(db.String(20), ForeignKey('orders.orderid',onupdate='CASCADE',ondelete='CASCADE'))
    orders = relationship("Orders", backref="fkOrder")

创建表 当表存在不操作 表结构进行修改后也不会进行操作

connection.base.metadata.create_all()

可以用插件sqlalchemy-migrate协助处理

3.增

   import DataModel.Test

    session = self.connection.session()
    try:
        re = DataModel.Test.Orders(orderid = '20170607_001',name = 'wang wu')
        session.add(re)
        session.flush()
        re = DataModel.Test.Details(orderid = '20170607_001',detailname = 'wang wu detailname')
        session.add(re)
        session.flush()
        re = DataModel.Test.Details(orderid = '20170607_001',detailname = 'wang wu detailname')
        session.add(re)
        session.flush()
        session.commit()
    except Exception as e:
        session.rollback()

4.删

    

from sqlalchemy import text
        re = session.query(DataModel.Job.Receives).filter(text("id =2"))
        session.delete(re[0])

5.改

    

from sqlalchemy import text
        re = session.query(DataModel.Job.Receives).filter(text("id =3"))
        re[0].data = '{"name":"zhangsan1"}'
        sql = str(session.add(re[0]))
        session.commit()

6.查

import DataModel.Job
session = self.connection.session()
try:
    # res = session.query(DataModel.Job.Receives).order_by(DataModel.Job.Receives.id)
    # res = session.query(DataModel.Job.Receives.id,DataModel.Job.Receives.jobid).all()
    # res = session.query(DataModel.Job.Receives).all()[2:4]
    # res = session.query(DataModel.Job.Receives).filter(DataModel.Job.Receives.id == 1)
    # res = session.query(DataModel.Job.Receives).filter(DataModel.Job.Receives.id != 1)
    # res = session.query(DataModel.Job.Receives).filter(DataModel.Job.Receives.jobid.like('%0%'),DataModel.Job.Receives.id.in_([1,3]))
    # res = session.query(DataModel.Job.Receives).filter(DataModel.Job.Receives.jobid.like('%0%'),
    #                                                    DataModel.Job.Receives.id > 1)

    from sqlalchemy import and_,or_
    # res = session.query(DataModel.Job.Receives).filter(and_(DataModel.Job.Receives.jobid.like('%0%'),
    #                                                    DataModel.Job.Receives.id == 2))
    # res = session.query(DataModel.Job.Receives).filter(or_(DataModel.Job.Receives.id == 1,
    #                                                         DataModel.Job.Receives.id == 2))
    ########################
    # res = session.query(DataModel.Job.Receives).filter(or_(DataModel.Job.Receives.id == 1,
    #                                                        DataModel.Job.Receives.id == 2)).first()
    # result = result + '\n\r' + str(res.id) + res.data + res.jobid
    ########################
    from sqlalchemy import text
    # res = session.query(DataModel.Job.Receives).filter(text("id > 0 or id =1"))
    # res = session.query(DataModel.Job.Receives).from_statement(text("select * from receives where id > 1"))
    ################
    # res = session.query(DataModel.Job.Receives).filter(text("id > 0 or id =1")).count()
    # result = str(res)           # 使用from_statement 则不能统计
    #################
    # res = session.query(DataModel.Job.Receives).filter(text("id > 0 or id =1")).limit(2)
    res = session.query(DataModel.Job.Receives).filter(text("id > 0 or id =1"))[2:3]

    for m in res:
        result = result + '\n\r' + str(m.id) + m.data + m.jobid

7.修改单条记录时
按KEY值修改 非全字段对比 这样会造成多个地方同时修改 要想精确控制全字段对比 需要手写SQL方法

  1. 外键的实际应用中写法 ,可以多级外键 swagger.Tags = [tag,tag]

    class Swagger(swaggerConnection.Connection.base):

    __tablename__ = 'swagger'
    id = db.Column('id',db.Integer,primary_key=True,autoincrement=True)
    url = db.Column('url',db.String(200),unique=False,nullable=True)
    name = db.Column('name',db.String(200),unique=False,nullable=True)
    host = db.Column('host',db.String(200),unique=False,nullable=True)
    basePath = db.Column('basepath',db.String(200),unique=False,nullable=True)
    Tags = relationship("Tags", order_by="Tags.id", backref="swagger")
    

    class Tags(swaggerConnection.Connection.base):

    __tablename__ = 'tags'
    id = db.Column('id',db.Integer,primary_key=True,autoincrement=True)
    swaggerid = Column(Integer, ForeignKey('swagger.id',onupdate='CASCADE',ondelete='CASCADE'))
    name = db.Column('name',db.String(100),unique=False,nullable=True)
    description = db.Column('description',db.String(200),unique=False,nullable=True)
    Paths = relationship("Paths", order_by="Paths.id", backref="tags")