作者: 李镇伟

将Jira获取的UTC时间转本地时间yyyy-MM-dd’T’HH:mm:ss

通过API获得jira 备注(comment)的更新时间,发现获得的UTC时间格式为
2018-08-14T02:52:22.216+0000
这个时候,如果需要转换成datetime :yyyy-MM-dd'T'HH:mm:ss格式,
或者date:yyyy-MM-dd,可以用下面的代码:

#!/usr/bin/python
# -*- coding:utf-8 -*-
import re
import time
from datetime import datetime
def utc2local(utc_st):
    # UTC时间转本地时间(+8:00)
    now_stamp = time.time()
    local_time = datetime.fromtimestamp(now_stamp)
    utc_time = datetime.utcfromtimestamp(now_stamp)
    offset = local_time - utc_time
    local_st = utc_st + offset
    return local_st
def local2utc(local_st):
    # 本地时间转UTC时间(-8:00)
    time_struct = time.mktime(local_st.timetuple())
    utc_st = datetime.utcfromtimestamp(time_struct)
    return utc_st
def utc_format(utcstr):
    """
    将不标准的utc时间字符串转换成datetime格式
    :param utcstr: 不标准的utc字符串,如‘2018-04-23T03:43:35.000+0000’
    :return:
    """
    utcstr = re.sub('.\d\d\d\+0000', '', utcstr, count=1)
    try:
        UTC_FORMAT = "%Y-%m-%dT%H:%M:%S"
        d_time = datetime.strptime(utcstr, UTC_FORMAT)
    except Exception:
        UTC_FORMAT = "%Y-%m-%d %H:%M:%S"
        d_time = datetime.strptime(utcstr, UTC_FORMAT)
    return d_time
def get_local_date(utcstr):
    """
    将jira返回的str类型的时间,转换成datetime格式,并去除日期之后的内容(提供给SprintDailyIssuesBar使用的日期处理接口)
    :param utcstr: jira返回的time字符串
    :return:datetime格式
    """
    utc_st = utc_format(utcstr)
    # print utc_st
    local_st = utc2local(utc_st)
    # print local_st
    local_str = local_st.strftime('%Y-%m-%d')
    local_date = datetime.strptime(local_str, "%Y-%m-%d")
    # print local_date
    return local_date
def get_local_datetime_str(utcstr):
    """
    将jira返回的str类型的UTC时间,转换成str类型的local time,包含具体的时、分、秒(提供给tableData使用,转换时间)
    :param utcstr: jira返回的time字符串
    :return:string
    """
    utc_st = utc_format(utcstr)
    # print utc_st
    local_st = utc2local(utc_st)
    # print local_st
    local_str = local_st.strftime('%Y-%m-%d %H:%M:%S')
    return local_str
 if __name__ == '__main__':
     utcstr1 = '2018-08-14T02:52:22.216+0000'
     tt=get_local_datetime_str(utcstr1)
     print(tt)

将Jira获取的UTC时间转本地时间yyyy-MM-dd’T’HH:mm:ss

通过API获得jira 备注(comment)的更新时间,发现获得的UTC时间格式为
2018-08-14T02:52:22.216+0000
这个时候,如果需要转换成datetime :yyyy-MM-dd'T'HH:mm:ss格式,
或者date:yyyy-MM-dd,可以用下面的代码:

#!/usr/bin/python
# -*- coding:utf-8 -*-
import re
import time
from datetime import datetime
def utc2local(utc_st):
    # UTC时间转本地时间(+8:00)
    now_stamp = time.time()
    local_time = datetime.fromtimestamp(now_stamp)
    utc_time = datetime.utcfromtimestamp(now_stamp)
    offset = local_time - utc_time
    local_st = utc_st + offset
    return local_st
def local2utc(local_st):
    # 本地时间转UTC时间(-8:00)
    time_struct = time.mktime(local_st.timetuple())
    utc_st = datetime.utcfromtimestamp(time_struct)
    return utc_st
def utc_format(utcstr):
    """
    将不标准的utc时间字符串转换成datetime格式
    :param utcstr: 不标准的utc字符串,如‘2018-04-23T03:43:35.000+0000’
    :return:
    """
    utcstr = re.sub('.ddd+0000', '', utcstr, count=1)
    try:
        UTC_FORMAT = "%Y-%m-%dT%H:%M:%S"
        d_time = datetime.strptime(utcstr, UTC_FORMAT)
    except Exception:
        UTC_FORMAT = "%Y-%m-%d %H:%M:%S"
        d_time = datetime.strptime(utcstr, UTC_FORMAT)
    return d_time
def get_local_date(utcstr):
    """
    将jira返回的str类型的时间,转换成datetime格式,并去除日期之后的内容(提供给SprintDailyIssuesBar使用的日期处理接口)
    :param utcstr: jira返回的time字符串
    :return:datetime格式
    """
    utc_st = utc_format(utcstr)
    # print utc_st
    local_st = utc2local(utc_st)
    # print local_st
    local_str = local_st.strftime('%Y-%m-%d')
    local_date = datetime.strptime(local_str, "%Y-%m-%d")
    # print local_date
    return local_date
def get_local_datetime_str(utcstr):
    """
    将jira返回的str类型的UTC时间,转换成str类型的local time,包含具体的时、分、秒(提供给tableData使用,转换时间)
    :param utcstr: jira返回的time字符串
    :return:string
    """
    utc_st = utc_format(utcstr)
    # print utc_st
    local_st = utc2local(utc_st)
    # print local_st
    local_str = local_st.strftime('%Y-%m-%d %H:%M:%S')
    return local_str
 if __name__ == '__main__':
     utcstr1 = '2018-08-14T02:52:22.216+0000'
     tt=get_local_datetime_str(utcstr1)
     print(tt)

图解OWASP ZAP录制登录请求,并且进行SQL注入测试

好了,废话不多说,下面几张图请按顺序观看,是作者用OWASP ZAP对某一个网站进行登录的SQL注入测试,网址和登录密码,作者已经打码了,如有侵权或引起其他不适,请联系作者。
——————————————第一步——————————————

——————————————第二步——————————————

——————————————第三步——————————————
——————————————第四步——————————————
——————————————第五步——————————————

 

记录一次我做的influxDB性能测试

InfluxDB性能测试报告
被测环境:
腾讯云

CPU 内存 带宽 版本号
4核 16G 1Gbit/s Ubuntu 4.8.4-2ubuntu1~14.04.3

 
地址:
 
被测程序:
Docker下安装的influxDB 端口8086
 
压测环境:
腾讯云

CPU 内存 带宽 版本号
2核 8G 1Gbit/s Ubuntu 4.8.4-2ubuntu1~14.04.3

 
地址:
 
测试程序:
从github上找的influxdata公司提供的两款测试工具
influx-stress 用于写入测试
influxdb-comparisons用于查询测试
 
测试场景:

写入测试
工具名称 influx-stress
 
工具github地址 https://github.com/influxdata/influx-stress
测试原理 该工具是通过go语言的fasthttp库编写的。
1.     会在服务器上创建一个数据库stress
2.     然后创建一个MEASUREMENT(类似关系数据库的表)名为ctr
该表有time,n.some三个字段
3.     不断的向stress数据库的ctr表插入数据,每次插入的数据都包含三个字段。每一条数据称为一个points。
插入数据的方法是通过influxDB的HTTP API 发送请求(POST /write?db=stress)
 
测试命令 influx-stress insert -r 60s –strict –pps 200000 –host http://10.XX.XX.XX:8086
 
测试程序运行结果
Points Per Second(发起请求) Write Throughput(points/s)
(数据库实际处理结果)
CPU平均利用率
200000 199713 33%
300000 299280 45%
400000 392873 62%
500000 491135 80%
600000 593542 90%
650000 606036 93%
700000 613791 95%

测试结论:最大的吞吐量为每秒写入60万条数据。这之后,每秒发送的points再多,吞吐量也不会增加,同时CPU利用率已达90%。
 

查询测试
工具名称 influxdb-comparisons
 
工具github地址 https://github.com/influxdata/influxdb-comparisons
测试原理 该工具是通过go语言的fasthttp库编写的。
1.     会在服务器上创建一个数据库benchmark_db
2.     然后创建9个MEASUREMENT :cpu,disk,diskio,kernel,mem,net,nginx,postgresl
每个measurement 有2160行数据。
3.     通过http GET请求”GET /query?db=benchmark_db“查询cpu这张表。
查询语句为:SELECT max(usage_user) from cpu where (hostname = ‘host_0’) and time >= ‘2016-01-01T01:16:32Z’ and time < ‘2016-01-01T02:16:32Z’ group by time(1m)
可以取出61条数据。
 
测试命令 ./bulk_query_gen -query-type “1-host-1-hr” | ./query_benchmarker_influxdb -urls http://10.XX.XX.XX:8086 -limit 1000
 
测试程序运行结果
查询命令执行次数
(-limit)
命令最短执行时间 每条命令平均执行时间 命令最大执行时间 总耗时
100 1.20ms 1.69ms 4.36ms 0.2sec
200 1.20ms 1.71ms 7.40ms 0.3sec
300 1.25ms 1.73ms 7.54ms 0.5sec
400 1.21ms 1.71ms 7.54ms 0.7sec
500 1.20ms 1.70ms 7.54ms 0.8sec
600 1.17ms 1.67ms 7.54ms 1.0sec
700 1.14ms 1.66ms 8.33ms 1.2sec
800 1.14ms 1.65ms 8.33ms 1.3sec
900 1.14ms 1.63ms 8.33ms 1.5sec
1000 1.14ms 1.64ms 8.33ms 1.6sec

测试结论:因为该工具最大只能测到读取1000条数据,所以没有继续加大压力测试。查询操作的消耗时间因为受到被查询表的数据量和查询语句的复杂性影响,所以在influxDate官方给出的被查表和查询语句下,算出来是平均每秒执行600次查询。
 
 
 
 

wxpython 的pub/sub发布订阅,夸窗口传递信息

我们经常会用到两个窗口之间互相传递信息,或者把一个窗口里,文本框输入的值,传递到另外一个frame的另外一个文本框里,
这个时候,我们可以使用wxpython的pub/sub方法。
test.py


class Main(wx.App):
          def __init__(self):
                  #mainFrame 是用wxglade画的一个frame导出来的python文件
                   self.frame1 = mainFrame.MyFrame(None, wx.ID_ANY, "")
                   self.frame1.Show()
                   self.children=test2.children()
                  #定义一个name1属性,值来自于窗口上的文本框控件
                   self.name1 = self.frame1.text_ctrl_1
                  #  离开焦点,就把fram1的文本框里的值传入children的另外一个文本框内
                  self.name1 .Bind(wx.EVT_COMMAND_KILL_FOCUS, self.save)
                  #发布一个叫in_sync的主题,触发sync函数
                   pub.subscribe(self.sync, "in_sync")
          def sync(self, msg):
                  #给children的text_ctrl_2字段设置值
                  self.children.frame.text_ctrl_2.SetValue(msg)
          def save(self,evt):
                    value=self.name1.GetValue()
                    #调用一下in_sync方法,如果in_sync方法在别的class里,
                    #也是可以调用pub.sendMessage成功的
                    self.children.in_sync(value)

test2.py

class children(wx.App):
           def __init__(self):
                  #mainFrame 是用wxglade画的一个frame导出来的python文件
                   self.frame = mainFrame.MyFrame(None, wx.ID_ANY, "")
                   self.frame.Show()
           def in_sync(text):
                 #订阅"in_sync"主题
                 wx.CallAfter(pub.sendMessage, "in_sync", msg=text)

wxpython 根据item的名字找到tree_ctrl对应的节点

业务场景,需要在一个tree_ctrl中找到一个节点,并且给该节点添加子节点

def get_item_by_label(self, tree, search_text, root_item):
    item, cookie = tree.GetFirstChild(root_item)
    while item.IsOk():
        text = tree.GetItemText(item)
        if text.lower() == search_text.lower():
            return item
        if tree.ItemHasChildren(item):
            match = self.get_item_by_label(tree, search_text, item)
            if match.IsOk():
                return match
        item, cookie = tree.GetNextChild(root_item, cookie)
    return wx.TreeItemId()
result = get_item_by_label(tree, '已有节点', tree.GetRootItem())
if result.IsOk():
    print('We have a match!')
    new_item = tree.AppendItem(result , "新节点")

wxpython一个event,多个handler,先绑定的后执行

Q:为什么会有一次event,多次handler的需求呢?
A:因为wxpython 目前有一个BUG,在一个event函数中,无法使用两次Dialog.showModal方法。当第一个Dialog消失后,第二个dialog再弹出,会造成系统卡死。所以必须把两个dialog.showModal放入两个event中。
绑定规则:先绑定的后执行
给按钮sync_button 绑定三个事件,第一次执行的在下,第二次执行的在上,如下:
给按钮绑定事件

        self.sync_button.Bind(wx.EVT_BUTTON, self.sync_three_event)
        self.sync_button.Bind(wx.EVT_BUTTON, self.sync_two_event)
        self.sync_button.Bind(wx.EVT_BUTTON, self.sync_one_event)

编写事件的event

    def sync_one_event(self, event):
        print("第一次触发事件" )
        event.Skip()
    def sync_two_event(self, event):
        print("第二次触发事件" )
        event.Skip()
    def sync_three_event(self, event):
        print("第三次触发事件" )
        event.Skip()

最后触发的结果是:

第一次触发事件
第二次触发事件
第三次触发事件

实现wxpython的拖拽上传功能

实现wxpython的拖拽上传功能
1.从FileDropTarget继承

···
class MyFileDropTarget(wx.FileDropTarget):
def init(self):
wx.FileDropTarget.init(self)
def OnDropFiles(self, x, y, filepath):
# file=os.path.basename(filepath[0])
#各种文件操作之类的
return False ···

2.给panel绑定拖拽功能

    filedrop = MyFileDropTarget()
    self.frame.panel_2.SetDropTarget(filedrop)

3.注意事项:
一次只能拖拽一个文件上去,如果一次拖拽A,B,C三个文件。最后filepath只能获取到A文件,B,C丢失

python2.7-wxpython4.0.1-pyinstaller打包的正确用法

hi 各位看官,本文是截止2018年7月4日,基于python2.7开发wxpython时的打包正确用法。(2018年11月16日,发现pyinstall 3.4版本解决了这个问题了)
坑1:
wxpython的最新版本为4.0.3 但是因为4.0.3引入了新的pubsub 4.0 不兼容python2.7。所以如果用python2.7的同学必须降级到wxpython 4.0.1版本
坑2:
打包方面,我们可以用pyinstaller打包。但是pip上,pyinstaller最新的版本是3.3.1 版本,此版本上有bug https://github.com/pyinstaller/pyinstaller/issues/2215
但是后期,pyinstall的作者修复了此bug在dev版本上,所以我们只有去github上 安装最新的dev版本才能打包成功
踩坑表现:

Traceback (most recent call last):
  File "<string>", line 41, in <module>
  File "<string>", line 36, in walk_packages
  File "<string>", line 20, in walk_packages
  File "d:program filespythonpython27libsite-packageswx-3.0-mswwxlibpubsubcorearg1__init__.py", line 16, in <module>
    raise RuntimeError(msg)
RuntimeError: Should not import this directly, used by pubsub.core if applicable

出现pubsub报错,因为wxpython 2.8.0之前的版本用的是corearg1 所以为了能顺利打包,我们要进行如下操作:
填坑方法:
1.pip装wxpython 4.0.1版本

pip install wxpython==4.0.1

2.pip装dev版本pyinstaller

 pip install git+https://github.com/pyinstaller/pyinstaller

3.重新打包主入口main.py

pyinstaller -D main.py

wxpython之tree_ctrl图标与点击事件


如何用wxpython展示一个如图所示的的树呢?
wxpython的treectrl功能可以实现。
1.首先我们可以用wxglade画前端frame界面,添加一个TreeCtrl ,或者多个TreeCtrl,添加root.每一个tree只能有一个root

self.tree_ctrl_1 = wx.TreeCtrl(self.panel_1, wx.ID_ANY)
my_defect_root =self.my_tree.AddRoot("My Defect")

2.然后给设置图片list 用来给根节点和树节点放不一样的图片

self.image_list = wx.ImageList(16, 16)
self.case_icon =self.image_list.Add(wx.Image("resource/image/icon/bookmark.png",
                                              wx.BITMAP_TYPE_PNG).Scale(16, 16).ConvertToBitmap())
self.folder_icon =self.image_list.Add(wx.Image("resource/image/icon/document.png",
                                                wx.BITMAP_TYPE_PNG).Scale(16, 16).ConvertToBitmap())

3.然后给树设置imagelist

self.project_tree.SetImageList(self.image_list)

#注意千万不能用AssignImageList ,这样写虽然运行没问题,但是关闭窗口时会导致crash,一定要用SetImageList
4.给每一个节点设置图片和文字

status_node =self.my_tree.AppendItem(my_defect_root, “open”)
self.my_tree.SetItemImage(status_node, self.folder_icon, wx.TreeItemIcon_Normal)

5.给节点绑定双击事件

self.my_tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.show_defect_info)
def show_defect_info(self, event):
    item = event.GetItem()
    self.my_tree.Expand(item)
    print(self.my_tree.GetItemText(item))

苏ICP备18047533号-1