Have a reset then enjoy the next

Hopefully ~~
2020-06-29
Hopefully ~~
2020-06-29

深圳住房公积金验证码 识别破解

1212.PNG

 
http://gjj.sz.gov.cn/fzgn/zfcq/index.html
 
比较常规的验证码,使用keras全连接层,cv切割后每个字符只需要20个样本就达到准确率99%。
需要模型或者代码的私聊。
继续阅读 »
1212.PNG

 
http://gjj.sz.gov.cn/fzgn/zfcq/index.html
 
比较常规的验证码,使用keras全连接层,cv切割后每个字符只需要20个样本就达到准确率99%。
需要模型或者代码的私聊。 收起阅读 »

git命令行查看图形化的分支信息与commit 缩写id

git
在命令行下面,有时候需要可视化的观察git的分支情况以及commit id的缩写值。
可以使用 git log 加若干参数
 
git log --graph --pretty=oneline --abbrev-commit

效果是这样的:

img1.PNG

 
而实际在source tree中是这样的:

2.png

 
 
继续阅读 »
在命令行下面,有时候需要可视化的观察git的分支情况以及commit id的缩写值。
可以使用 git log 加若干参数
 
git log --graph --pretty=oneline --abbrev-commit

效果是这样的:

img1.PNG

 
而实际在source tree中是这样的:

2.png

 
  收起阅读 »

(1412, 'Table definition has changed, please retry transaction')

python访问数据库时报这个错误:
(1412, 'Table definition has changed, please retry transaction')

一个原因是因为多个线程操作数据库,当前的cursor对应的数据库被切换到其他库了。
比如 cursor在数据库A,正在不断query一条语句,然后另一个线程在在切换cursor到另外一个数据库B。
 
继续阅读 »
python访问数据库时报这个错误:
(1412, 'Table definition has changed, please retry transaction')

一个原因是因为多个线程操作数据库,当前的cursor对应的数据库被切换到其他库了。
比如 cursor在数据库A,正在不断query一条语句,然后另一个线程在在切换cursor到另外一个数据库B。
  收起阅读 »

PyQt5自定义控件

PyQt5包含种类丰富的控件。但能满足所有需求的控件库是不存在的。通常控件库只提供了像按钮、文本控件、滑块等最常用的控件。但如果需要某种特殊的控件,我们只能自己动手来实现。 自定义控件需要使用工具库提供的绘图工具,可能有两种方式:在已有的控件上进行拓展或从头开始创建自定义控件。
 
Burning widget(烧录控件)
这个控件可能会在Nero,K3B或其他CD/DVD烧录软件中见到。
 
# -*- coding: utf-8 -*-

"""
PyQt5 tutorial

In this example, we create a custom widget.
"""
import sys
from PyQt5.QtWidgets import (QWidget, QSlider, QApplication,
QHBoxLayout, QVBoxLayout)
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QFont, QColor, QPen


class Communicate(QObject):
updateBW = pyqtSignal(int)


class BurningWidget(QWidget):
def __init__(self):
super().__init__()

self.initUI()

def initUI(self):

self.setMinimumSize(1, 30)
self.value = 75
self.num = [75, 150, 225, 300, 375, 450, 525, 600, 675]

def setValue(self, value):

self.value = value

def paintEvent(self, e):

qp = QPainter()
qp.begin(self)
self.drawWidget(qp)
qp.end()

def drawWidget(self, qp):

font = QFont('Serif', 7, QFont.Light)
qp.setFont(font)

size = self.size()
w = size.width()
h = size.height()

step = int(round(w / 10.0))

till = int(((w / 750.0) * self.value))
full = int(((w / 750.0) * 700))

if self.value >= 700:

qp.setPen(QColor(255, 255, 255))
qp.setBrush(QColor(255, 255, 184))
qp.drawRect(0, 0, full, h)
qp.setPen(QColor(255, 175, 175))
qp.setBrush(QColor(255, 175, 175))
qp.drawRect(full, 0, till - full, h)

else:

qp.setPen(QColor(255, 255, 255))
qp.setBrush(QColor(255, 255, 184))
qp.drawRect(0, 0, till, h)

pen = QPen(QColor(20, 20, 20), 1,
Qt.SolidLine)

qp.setPen(pen)
qp.setBrush(Qt.NoBrush)
qp.drawRect(0, 0, w - 1, h - 1)

j = 0

for i in range(step, 10 * step, step):
qp.drawLine(i, 0, i, 5)
metrics = qp.fontMetrics()
fw = metrics.width(str(self.num[j]))
qp.drawText(i - fw / 2, h / 2, str(self.num[j]))
j = j + 1


class Example(QWidget):
def __init__(self):
super().__init__()

self.initUI()

def initUI(self):
sld = QSlider(Qt.Horizontal, self)
sld.setFocusPolicy(Qt.NoFocus)
sld.setRange(1, 750)
sld.setValue(75)
sld.setGeometry(30, 40, 150, 30)

self.c = Communicate()
self.wid = BurningWidget()
self.c.updateBW[int].connect(self.wid.setValue)

sld.valueChanged[int].connect(self.changeValue)
hbox = QHBoxLayout()
hbox.addWidget(self.wid)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)

self.setGeometry(300, 300, 390, 210)
self.setWindowTitle('Burning widget')
self.show()

def changeValue(self, value):
self.c.updateBW.emit(value)
self.wid.repaint()


if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在示例中我们使用了滑块与一个自定义控件。自定义控件受滑块控制。控件显示了媒体介质的容量和剩余空间。该控件的最小值为1,最大值为750。在值超过700时颜色变为红色。这通常意味着超刻(即实际写入光盘的容量超过刻录盘片官方标称容量的一种操作)。
 
BurningWidget控件通过QHBoxLayout与QVBoxLayout置于窗体的底部。
class BurningWidget(QWidget):

def __init__(self):
super().__init__()

 
烧录的控件,它基于QWidget
 
self.setMinimumSize(1, 30)
我们改变了控件的最小大小(高度),默认值为有点小。
font = QFont('Serif', 7, QFont.Light)
qp.setFont(font)
我们使用一个比默认要小的字体。
size = self.size()
w = size.width()
h = size.height()

step = int(round(w / 10.0))


till = int(((w / 750.0) * self.value))
full = int(((w / 750.0) * 700))

控件采用了动态绘制技术。窗体越大,控件也随之变大;反之亦然。这也是我们需要计算自定义控件的载体控件(即窗体)尺寸的原因。till参数定义了需要绘制的总尺寸,它根据slider控件计算得出,是整体区域的比例值。full参数定义了红色区域的绘制起点。注意在绘制时为取得较大精度而使用的浮点数运算。

实际的绘制分三个步骤。黄色或红黄矩形的绘制,然后是刻度线的绘制,最后是刻度值的绘制。
 
metrics = qp.fontMetrics()
fw = metrics.width(str(self.num[j]))
qp.drawText(i-fw/2, h/2, str(self.num[j]))
我们使用字体度量来绘制文本。我们必须知道文本的宽度,以中心垂直线。
def changeValue(self, value):

self.c.updateBW.emit(value)
self.wid.repaint()
当滑块发生移动时,changeValue()方法会被调用。在方法内我们触发了一个自定义的updateBW信号,其参数是当前滚动条的值。该值被用于计算Burning widget的容量值。然后对控件进行重绘。
 

12345.PNG

 
继续阅读 »
PyQt5包含种类丰富的控件。但能满足所有需求的控件库是不存在的。通常控件库只提供了像按钮、文本控件、滑块等最常用的控件。但如果需要某种特殊的控件,我们只能自己动手来实现。 自定义控件需要使用工具库提供的绘图工具,可能有两种方式:在已有的控件上进行拓展或从头开始创建自定义控件。
 
Burning widget(烧录控件)
这个控件可能会在Nero,K3B或其他CD/DVD烧录软件中见到。
 
# -*- coding: utf-8 -*-

"""
PyQt5 tutorial

In this example, we create a custom widget.
"""
import sys
from PyQt5.QtWidgets import (QWidget, QSlider, QApplication,
QHBoxLayout, QVBoxLayout)
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QFont, QColor, QPen


class Communicate(QObject):
updateBW = pyqtSignal(int)


class BurningWidget(QWidget):
def __init__(self):
super().__init__()

self.initUI()

def initUI(self):

self.setMinimumSize(1, 30)
self.value = 75
self.num = [75, 150, 225, 300, 375, 450, 525, 600, 675]

def setValue(self, value):

self.value = value

def paintEvent(self, e):

qp = QPainter()
qp.begin(self)
self.drawWidget(qp)
qp.end()

def drawWidget(self, qp):

font = QFont('Serif', 7, QFont.Light)
qp.setFont(font)

size = self.size()
w = size.width()
h = size.height()

step = int(round(w / 10.0))

till = int(((w / 750.0) * self.value))
full = int(((w / 750.0) * 700))

if self.value >= 700:

qp.setPen(QColor(255, 255, 255))
qp.setBrush(QColor(255, 255, 184))
qp.drawRect(0, 0, full, h)
qp.setPen(QColor(255, 175, 175))
qp.setBrush(QColor(255, 175, 175))
qp.drawRect(full, 0, till - full, h)

else:

qp.setPen(QColor(255, 255, 255))
qp.setBrush(QColor(255, 255, 184))
qp.drawRect(0, 0, till, h)

pen = QPen(QColor(20, 20, 20), 1,
Qt.SolidLine)

qp.setPen(pen)
qp.setBrush(Qt.NoBrush)
qp.drawRect(0, 0, w - 1, h - 1)

j = 0

for i in range(step, 10 * step, step):
qp.drawLine(i, 0, i, 5)
metrics = qp.fontMetrics()
fw = metrics.width(str(self.num[j]))
qp.drawText(i - fw / 2, h / 2, str(self.num[j]))
j = j + 1


class Example(QWidget):
def __init__(self):
super().__init__()

self.initUI()

def initUI(self):
sld = QSlider(Qt.Horizontal, self)
sld.setFocusPolicy(Qt.NoFocus)
sld.setRange(1, 750)
sld.setValue(75)
sld.setGeometry(30, 40, 150, 30)

self.c = Communicate()
self.wid = BurningWidget()
self.c.updateBW[int].connect(self.wid.setValue)

sld.valueChanged[int].connect(self.changeValue)
hbox = QHBoxLayout()
hbox.addWidget(self.wid)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)

self.setGeometry(300, 300, 390, 210)
self.setWindowTitle('Burning widget')
self.show()

def changeValue(self, value):
self.c.updateBW.emit(value)
self.wid.repaint()


if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

在示例中我们使用了滑块与一个自定义控件。自定义控件受滑块控制。控件显示了媒体介质的容量和剩余空间。该控件的最小值为1,最大值为750。在值超过700时颜色变为红色。这通常意味着超刻(即实际写入光盘的容量超过刻录盘片官方标称容量的一种操作)。
 
BurningWidget控件通过QHBoxLayout与QVBoxLayout置于窗体的底部。
class BurningWidget(QWidget):

def __init__(self):
super().__init__()

 
烧录的控件,它基于QWidget
 
self.setMinimumSize(1, 30)
我们改变了控件的最小大小(高度),默认值为有点小。
font = QFont('Serif', 7, QFont.Light)
qp.setFont(font)
我们使用一个比默认要小的字体。
size = self.size()
w = size.width()
h = size.height()

step = int(round(w / 10.0))


till = int(((w / 750.0) * self.value))
full = int(((w / 750.0) * 700))

控件采用了动态绘制技术。窗体越大,控件也随之变大;反之亦然。这也是我们需要计算自定义控件的载体控件(即窗体)尺寸的原因。till参数定义了需要绘制的总尺寸,它根据slider控件计算得出,是整体区域的比例值。full参数定义了红色区域的绘制起点。注意在绘制时为取得较大精度而使用的浮点数运算。

实际的绘制分三个步骤。黄色或红黄矩形的绘制,然后是刻度线的绘制,最后是刻度值的绘制。
 
metrics = qp.fontMetrics()
fw = metrics.width(str(self.num[j]))
qp.drawText(i-fw/2, h/2, str(self.num[j]))
我们使用字体度量来绘制文本。我们必须知道文本的宽度,以中心垂直线。
def changeValue(self, value):

self.c.updateBW.emit(value)
self.wid.repaint()
当滑块发生移动时,changeValue()方法会被调用。在方法内我们触发了一个自定义的updateBW信号,其参数是当前滚动条的值。该值被用于计算Burning widget的容量值。然后对控件进行重绘。
 

12345.PNG

  收起阅读 »

Windows安装pyminizip

python3直接安装会报错:
pip install pyminizip
 电脑需要安装vc的编译库,或者在其他机子上把pyd文件拷贝到程序的当前目录。
python3直接安装会报错:
pip install pyminizip
 电脑需要安装vc的编译库,或者在其他机子上把pyd文件拷贝到程序的当前目录。

996走起

最近996真起劲
最近996真起劲

win10 vbs无法隐藏执行批处理问题

比如语句:
Set ws = CreateObject("Wscript.Shell") 
ws.run "cmd /c D:\新建\diff.bat",vbhide
WScript.sleep 1000
始终无法执行,莫名其妙。 
通过换路径执行,发现是路径不能有中文。。。。
居然windows也有这种中文路径问题。
 
win10 vbs中不能有中文路径名
继续阅读 »
比如语句:
Set ws = CreateObject("Wscript.Shell") 
ws.run "cmd /c D:\新建\diff.bat",vbhide
WScript.sleep 1000
始终无法执行,莫名其妙。 
通过换路径执行,发现是路径不能有中文。。。。
居然windows也有这种中文路径问题。
 
win10 vbs中不能有中文路径名 收起阅读 »

redis desktop manager windows客户端

原来用的QT写的。
怪不得这么垃圾。。。。。
原来用的QT写的。
怪不得这么垃圾。。。。。

pyqt5 QRect在哪个类

最新的版本是在 QtCore里面的
 
from PyQt5.QtCore import Qt,QRect

 
最新的版本是在 QtCore里面的
 
from PyQt5.QtCore import Qt,QRect

 

分享一个电影网站 insiji.com

 https://insiji.com/
貌似电影比较新,也比较清晰。 目前良心的站点不多了。
 
在线看挺流畅的,不过不登录没得下载。 只好抓包,把ts文件下载后再合并。
 https://insiji.com/
貌似电影比较新,也比较清晰。 目前良心的站点不多了。
 
在线看挺流畅的,不过不登录没得下载。 只好抓包,把ts文件下载后再合并。

2020-03-27 新事情坚持

持续一周的出差,学到的一些东西。
 
接下来的30天,要养成的习惯:
 
1. 早睡早起
2. 持续比例的输出。(有输入就要有输出)
3. 锻炼身体
4. 先专注一件事情,让他变为习惯后再攻克另外一件事情。
持续一周的出差,学到的一些东西。
 
接下来的30天,要养成的习惯:
 
1. 早睡早起
2. 持续比例的输出。(有输入就要有输出)
3. 锻炼身体
4. 先专注一件事情,让他变为习惯后再攻克另外一件事情。

忘记的QQ密码


曾经用了十多年的QQ忘记了密码,只有选择找回,找回密码问题是我的梦想是什么,过了这么多年,完全忘了当时是怎么回答的,就开始挨个慢慢试,房子,钱,车,工作,都不对,直到那时才意识到,弄丢的并QQ密码,而是梦想
 

曾经用了十多年的QQ忘记了密码,只有选择找回,找回密码问题是我的梦想是什么,过了这么多年,完全忘了当时是怎么回答的,就开始挨个慢慢试,房子,钱,车,工作,都不对,直到那时才意识到,弄丢的并QQ密码,而是梦想
 

windows下logstash6.5安装配置 网上的教程是linux,有坑

https://www.cnblogs.com/jstarseven/p/7704893.html
百度里搜到的logstash安装配置教程 千篇一律都是这样子。
 
启动服务测试一下是否安装成功:
cd bin
./logstash -e 'input { stdin { } } output { stdout {} }'

上面的是linux运行的。
windows下把logstash改为logstash.bat 然后运行。
 
报错:
ERROR: Unknown command '{'

See: 'bin/logstash --help'
[ERROR] 2020-02-28 10:04:29.307 [main] Logstash - java.lang.IllegalStateException: Logstash stopped processing because of an error: (SystemExit) exit

后来搜了下国外的网站。原来问题出在那个单引号上,把单引号改为双引号就可以了。
 
继续阅读 »
https://www.cnblogs.com/jstarseven/p/7704893.html
百度里搜到的logstash安装配置教程 千篇一律都是这样子。
 
启动服务测试一下是否安装成功:
cd bin
./logstash -e 'input { stdin { } } output { stdout {} }'

上面的是linux运行的。
windows下把logstash改为logstash.bat 然后运行。
 
报错:
ERROR: Unknown command '{'

See: 'bin/logstash --help'
[ERROR] 2020-02-28 10:04:29.307 [main] Logstash - java.lang.IllegalStateException: Logstash stopped processing because of an error: (SystemExit) exit

后来搜了下国外的网站。原来问题出在那个单引号上,把单引号改为双引号就可以了。
  收起阅读 »

薅“疫情公益”羊毛,黑产恶意爬取各大出版社电子书上万册

疫情以来,所有企业都上班延期选择在线复工,在我们居家自我隔离期间,极验观察爬虫却没有消停,反而爬虫行为更加活跃且更胜往常。本周五,我们和无糖信息一起聊聊线上爬虫的“疫情”。
 
 
疫情以来,所有企业都上班延期选择在线复工,在我们居家自我隔离期间,极验观察爬虫却没有消停,反而爬虫行为更加活跃且更胜往常。本周五,我们和无糖信息一起聊聊线上爬虫的“疫情”。
 
 

个人的知识星球

最近开通了知识星球,尝试在里面分享一些量化投资套利的学习教程。在里面你可以对不懂的问题进行提问,球主会一一的耐心解答。

ZSXQ_20200223_104730797.png

 
微信扫一扫加入我的知识星球
 
 
星球的第一篇文章
python获取全市场LOF基金折溢价数据并进行套利
 
 
市场是总共的LOF基金有301只(上图右下角的圈圈是所有基金的条数),而集思录上只有120只左右,所以有些溢价厉害(大于10%)的LOF基金并没有在集思录的网站上显示,这对于专注于套利的投资者来说,会损失很多潜在的套利机会。


lof.PNG

点击查看大图

我回复了该贴后,有大量的人私信我,问我能否提供一份这个数据,或者教对方如何获取这些数据。 因为人数众多,也没有那么多精力来一一回答。毕竟不同人的水平背景不一样,逐个回答起来也很累,所以就回答了几个朋友的问题后就一一婉拒了。


然后在几个投资群里,居然也有人提到这个数据,在咨询如何才能获取到这个完整的数据,并且可以实时更新显示。 因为我的微信群昵称和集思录是一样的,所以不少人@我,我也都简单的回复了下,是使用python抓取的数据,数据保存到Mysql和MongoDB。 代码行数不多,100行都不到。
 
具体实现在星球会有完整代码。
继续阅读 »
最近开通了知识星球,尝试在里面分享一些量化投资套利的学习教程。在里面你可以对不懂的问题进行提问,球主会一一的耐心解答。

ZSXQ_20200223_104730797.png

 
微信扫一扫加入我的知识星球
 
 
星球的第一篇文章
python获取全市场LOF基金折溢价数据并进行套利
 
 
市场是总共的LOF基金有301只(上图右下角的圈圈是所有基金的条数),而集思录上只有120只左右,所以有些溢价厉害(大于10%)的LOF基金并没有在集思录的网站上显示,这对于专注于套利的投资者来说,会损失很多潜在的套利机会。


lof.PNG

点击查看大图

我回复了该贴后,有大量的人私信我,问我能否提供一份这个数据,或者教对方如何获取这些数据。 因为人数众多,也没有那么多精力来一一回答。毕竟不同人的水平背景不一样,逐个回答起来也很累,所以就回答了几个朋友的问题后就一一婉拒了。


然后在几个投资群里,居然也有人提到这个数据,在咨询如何才能获取到这个完整的数据,并且可以实时更新显示。 因为我的微信群昵称和集思录是一样的,所以不少人@我,我也都简单的回复了下,是使用python抓取的数据,数据保存到Mysql和MongoDB。 代码行数不多,100行都不到。
 
具体实现在星球会有完整代码。 收起阅读 »

希望能够找到一个可以一起对彪的人

看了老男孩的某个视频教程,觉得这个挺有道理的。
目前貌似身边缺少一个这样的人,希望在这个网站上能够遇到一个这样的朋友。
有意的可以私聊吧。 非诚勿扰。
看了老男孩的某个视频教程,觉得这个挺有道理的。
目前貌似身边缺少一个这样的人,希望在这个网站上能够遇到一个这样的朋友。
有意的可以私聊吧。 非诚勿扰。

证券etf和券商etf的区别

证券etf是:国泰中证全指证券公司ETF(512880)LOF/ETF
 
而券商etf是:
华宝中证全指证券公司ETF (512000)LOF/ETF
 
二者都是指数/lof基金,而且持仓差不多都一样的。
 
证券etf的持仓:

chrome_UG24GjLJR3.png


 
券商etf的持仓:
 

chrome_uHevW3yNrG.png

 
不同的是规模,证券ETF的规模要比券商etf的规模要大得多。目前是2倍左右的差距【2019年的数据】。 所以如果你关心的是流动性,那么可以买证券ETF。
 
最新的规模【2020-06】其实二者在缩小,具体数据见文末。
 
证券ETF的规模是190亿

chrome_JpuQr1yMLG.png

 
而券商ETF规模为160亿。(最近增长比较多,笔者在1年前记录的数据为30亿,可以到http://fundf10.eastmoney.com/gmbd_512000.html 查看历史规模。现在券商ETF的规模翻了一番。

chrome_4vusy4V91e.png

 

 更多量化分析,关注公众号:可转债量化分析               
券商开户股票万一免5,基金申购一折,拖拉机6+1,关注公众号留言。
可转债手续费 百万分之二,一万块手续费才2分钱,没有最低限制(没有最低收1元,1毛这种)


 
(教你使用python进行量化分析股票,可转债数据)

 
继续阅读 »
证券etf是:国泰中证全指证券公司ETF(512880)LOF/ETF
 
而券商etf是:
华宝中证全指证券公司ETF (512000)LOF/ETF
 
二者都是指数/lof基金,而且持仓差不多都一样的。
 
证券etf的持仓:

chrome_UG24GjLJR3.png


 
券商etf的持仓:
 

chrome_uHevW3yNrG.png

 
不同的是规模,证券ETF的规模要比券商etf的规模要大得多。目前是2倍左右的差距【2019年的数据】。 所以如果你关心的是流动性,那么可以买证券ETF。
 
最新的规模【2020-06】其实二者在缩小,具体数据见文末。
 
证券ETF的规模是190亿

chrome_JpuQr1yMLG.png

 
而券商ETF规模为160亿。(最近增长比较多,笔者在1年前记录的数据为30亿,可以到http://fundf10.eastmoney.com/gmbd_512000.html 查看历史规模。现在券商ETF的规模翻了一番。

chrome_4vusy4V91e.png

 

 更多量化分析,关注公众号:可转债量化分析               
券商开户股票万一免5,基金申购一折,拖拉机6+1,关注公众号留言。
可转债手续费 百万分之二,一万块手续费才2分钱,没有最低限制(没有最低收1元,1毛这种)


 
(教你使用python进行量化分析股票,可转债数据)

  收起阅读 »

socketio中client的sio wait用法

用于阻塞当前的线程,后面的操作不会进行,直到服务端断开。
 
import time
import socketio

sio = socketio.Client()
start_timer = None


def send_ping():
global start_timer
start_timer = time.time()
sio.emit('ping_from_client')


@sio.event
def connect():
print('connected to server')
send_ping()


@sio.event
def pong_from_server(data):
global start_timer
latency = time.time() - start_timer
print('latency is {0:.2f} ms'.format(latency * 1000))
sio.sleep(1)
send_ping()


if __name__ == '__main__':
sio.connect('http://localhost:5000')
sio.wait()
print('next')

比如上述代码中,如果调用了sio.wait() , 那么next是不会被打印的。
 
如果注释掉后,那么next就可以正常被打印。
继续阅读 »
用于阻塞当前的线程,后面的操作不会进行,直到服务端断开。
 
import time
import socketio

sio = socketio.Client()
start_timer = None


def send_ping():
global start_timer
start_timer = time.time()
sio.emit('ping_from_client')


@sio.event
def connect():
print('connected to server')
send_ping()


@sio.event
def pong_from_server(data):
global start_timer
latency = time.time() - start_timer
print('latency is {0:.2f} ms'.format(latency * 1000))
sio.sleep(1)
send_ping()


if __name__ == '__main__':
sio.connect('http://localhost:5000')
sio.wait()
print('next')

比如上述代码中,如果调用了sio.wait() , 那么next是不会被打印的。
 
如果注释掉后,那么next就可以正常被打印。 收起阅读 »

dataframe 根据日期重采样 计算个数

按照日期重新采样,计算每天的个数new_df = df.resample('D').count()
按照日期重新采样,计算每天的个数new_df = df.resample('D').count()

失落

记住今天,铭记。
记住今天,铭记。

bandcamp移动开发更简单

mongodb日期条件查找

有时候用new Date() 不管用
有时候用new Date() 不管用

多线程调用yolo模型会出错(包括使用cv2载入yolo模型)

占坑。
 
多线程调用yolo模型会出错(包括使用cv2载入yolo模型)
 
占坑。
 
多线程调用yolo模型会出错(包括使用cv2载入yolo模型)
 

RuntimeError: `get_session` is not available when using TensorFlow 2.0.

这个问题是TensorFlow版本问题,在2.0以上get_session是被移除了。需要做一些修改,或者把tf降级。可以安装1.15版本
pip install tensorflow==1.15 --upgrade
Here, we will see how we can upgrade our code to work with tensorflow 2.0.

This error is usually faced when we are loading pre-trained model with tensorflow session/graph or we are building flask api over a pre-trained model and loading model in tensorflow graph to avoid collision of sessions while application is getting multiple requests at once or say in case of multi-threadinng

After tensorflow 2.0 upgrade, i also started facing above error in one of my project when i had built api of pre-trained model with flask. So i looked around in tensorflow 2.0 documents to find a workaround, to avoid this runtime error and upgrade my code to work with tensorflow 2.0 as well rather than downgrading it to tensorflow 1.x .

I had a project on which i had written tutorial as well on how to build Flask api on trained keras model of text classification and then use it in production

But this project was not working after tensorflow upgrade and was facing runtime error.

Stacktrace of error was something like below:

File "/Users/Upasana/Documents/playground/deploy-keras-model-in-production/src/main.py", line 37, in model_predict
with backend.get_session().graph.as_default() as g:
File "/Users/Upasana/Documents/playground/deploy-keras-model-in-production/venv-tf2/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py", line 379, in get_session
'`get_session` is not available '
RuntimeError: `get_session` is not available when using TensorFlow 2.0.
Related code to get model
with backend.get_session().graph.as_default() as g:
model = SentimentService.get_model1()
Related code to load model
def load_deep_model(self, model):
json_file = open('./src/mood-saved-models/' + model + '.json', 'r')
loaded_model_json = json_file.read()
loaded_model = model_from_json(loaded_model_json)

loaded_model.load_weights("./src/mood-saved-models/" + model + ".h5")

loaded_model._make_predict_function()
return loaded_model
get_session is removed in tensorflow 2.0 and hence not available.

so, in order to load saved model we switched methods. Rather than using keras’s load_model, we used tensorflow to load model so that we can load model using distribution strategy.

Note
The tf.distribute.Strategy API provides an abstraction for distributing your training across multiple processing units.

New code to get model
another_strategy = tf.distribute.MirroredStrategy()
with another_strategy.scope():
model = SentimentService.get_model1()
New code to load model
def load_deep_model(self, model):
loaded_model = tf.keras.models.load_model("./src/mood-saved-models/"model + ".h5")
return loaded_model
This worked and solved the problem with runtime error of get_session not available in tensorflow 2.0 . You can refer to Tensorflow 2.0 upgraded article too

Hope, this will solve your problem too. Thanks for following this article.
继续阅读 »
这个问题是TensorFlow版本问题,在2.0以上get_session是被移除了。需要做一些修改,或者把tf降级。可以安装1.15版本
pip install tensorflow==1.15 --upgrade
Here, we will see how we can upgrade our code to work with tensorflow 2.0.

This error is usually faced when we are loading pre-trained model with tensorflow session/graph or we are building flask api over a pre-trained model and loading model in tensorflow graph to avoid collision of sessions while application is getting multiple requests at once or say in case of multi-threadinng

After tensorflow 2.0 upgrade, i also started facing above error in one of my project when i had built api of pre-trained model with flask. So i looked around in tensorflow 2.0 documents to find a workaround, to avoid this runtime error and upgrade my code to work with tensorflow 2.0 as well rather than downgrading it to tensorflow 1.x .

I had a project on which i had written tutorial as well on how to build Flask api on trained keras model of text classification and then use it in production

But this project was not working after tensorflow upgrade and was facing runtime error.

Stacktrace of error was something like below:

File "/Users/Upasana/Documents/playground/deploy-keras-model-in-production/src/main.py", line 37, in model_predict
with backend.get_session().graph.as_default() as g:
File "/Users/Upasana/Documents/playground/deploy-keras-model-in-production/venv-tf2/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py", line 379, in get_session
'`get_session` is not available '
RuntimeError: `get_session` is not available when using TensorFlow 2.0.
Related code to get model
with backend.get_session().graph.as_default() as g:
model = SentimentService.get_model1()
Related code to load model
def load_deep_model(self, model):
json_file = open('./src/mood-saved-models/' + model + '.json', 'r')
loaded_model_json = json_file.read()
loaded_model = model_from_json(loaded_model_json)

loaded_model.load_weights("./src/mood-saved-models/" + model + ".h5")

loaded_model._make_predict_function()
return loaded_model
get_session is removed in tensorflow 2.0 and hence not available.

so, in order to load saved model we switched methods. Rather than using keras’s load_model, we used tensorflow to load model so that we can load model using distribution strategy.

Note
The tf.distribute.Strategy API provides an abstraction for distributing your training across multiple processing units.

New code to get model
another_strategy = tf.distribute.MirroredStrategy()
with another_strategy.scope():
model = SentimentService.get_model1()
New code to load model
def load_deep_model(self, model):
loaded_model = tf.keras.models.load_model("./src/mood-saved-models/"model + ".h5")
return loaded_model
This worked and solved the problem with runtime error of get_session not available in tensorflow 2.0 . You can refer to Tensorflow 2.0 upgraded article too

Hope, this will solve your problem too. Thanks for following this article.
收起阅读 »

yolo voc_label 源码分析

作用读取每个xml文件,把坐标转化为相对坐标,对应文件名保存起来
 
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join




sets = [('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]

# 20类
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog",
"horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]

# size w,h
# box x-min,x-max,y-min,y-max
def convert(size, box):
dw = 1. / size[0]
dh = 1. / size[1]
x = (box[0] + box[1]) / 2.0 # 中心点位置
y = (box[2] + box[3]) / 2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x * dw
w = w * dw
y = y * dh
h = h * dh # 全部转化为相对坐标
return (x, y, w, h)


def convert_annotation(year, image_id):
# 找到2个同样的文件
in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml' % (year, image_id))
out_file = open('VOCdevkit/VOC%s/labels/%s.txt' % (year, image_id), 'w')

tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)

for obj in root.iter('object'):
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult) == 1: # difficult ==1 的不要了
continue
cls_id = classes.index(cls) # 排在第几位
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
float(xmlbox.find('ymax').text))
# 传入的是w,h 与框框的周边
bb = convert((w, h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')


wd = getcwd()

for year, image_set in sets:
# ('2012', 'train') 循环5次
# 创建目录 一次性
if not os.path.exists('VOCdevkit/VOC%s/labels/' % (year)):
os.makedirs('VOCdevkit/VOC%s/labels/' % (year))

# 图片的id数据
image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt' % (year, image_set)).read().strip().split()

# 结果写入这个文件
list_file = open('%s_%s.txt' % (year, image_set), 'w')

for image_id in image_ids:
list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n' % (wd, year, image_id)) # 补全路径
convert_annotation(year, image_id)
list_file.close()

 
继续阅读 »
作用读取每个xml文件,把坐标转化为相对坐标,对应文件名保存起来
 
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join




sets = [('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]

# 20类
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog",
"horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]

# size w,h
# box x-min,x-max,y-min,y-max
def convert(size, box):
dw = 1. / size[0]
dh = 1. / size[1]
x = (box[0] + box[1]) / 2.0 # 中心点位置
y = (box[2] + box[3]) / 2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x * dw
w = w * dw
y = y * dh
h = h * dh # 全部转化为相对坐标
return (x, y, w, h)


def convert_annotation(year, image_id):
# 找到2个同样的文件
in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml' % (year, image_id))
out_file = open('VOCdevkit/VOC%s/labels/%s.txt' % (year, image_id), 'w')

tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)

for obj in root.iter('object'):
difficult = obj.find('difficult').text
cls = obj.find('name').text
if cls not in classes or int(difficult) == 1: # difficult ==1 的不要了
continue
cls_id = classes.index(cls) # 排在第几位
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
float(xmlbox.find('ymax').text))
# 传入的是w,h 与框框的周边
bb = convert((w, h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')


wd = getcwd()

for year, image_set in sets:
# ('2012', 'train') 循环5次
# 创建目录 一次性
if not os.path.exists('VOCdevkit/VOC%s/labels/' % (year)):
os.makedirs('VOCdevkit/VOC%s/labels/' % (year))

# 图片的id数据
image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt' % (year, image_set)).read().strip().split()

# 结果写入这个文件
list_file = open('%s_%s.txt' % (year, image_set), 'w')

for image_id in image_ids:
list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n' % (wd, year, image_id)) # 补全路径
convert_annotation(year, image_id)
list_file.close()

  收起阅读 »

docker run 和 create 区别

Technically, docker run = docker create + docker start
docker create command creates a writeable container from the image and prepares it for running. 
docker run command creates the container (same as docker create ) and starts it.
 
 
继续阅读 »
Technically, docker run = docker create + docker start
docker create command creates a writeable container from the image and prepares it for running. 
docker run command creates the container (same as docker create ) and starts it.
 
  收起阅读 »

用docker编译go代码


如果偶尔需要编译go代码,但是又不想要安装一堆乱七八糟的依赖和Go编译器,可以利用docker来实现。 应该是解决起来话费时间最小的。
1. 用文本编辑你的go代码,现在以hello world为例:
 
package main import "fmt" func main() {
/* 这是我的第一个简单的程序 */
fmt.Println("Hello, World!")
}

 
2. 然后直接使用docker执行编译。docker首先会自动去下载go的编译器,顺便把所有的依赖给解决掉

docker run --rm -v "$(pwd)":/usr/src/hello -w /usr/src/hello golang:1.3 go build -v
 
最后会在本地生成一个编译好的hello静态文件。
上述docker命令的具体含义就是把当前路径挂在到docker容器里头,然后切换到改到改路径下,然后进行编译。

继续阅读 »

如果偶尔需要编译go代码,但是又不想要安装一堆乱七八糟的依赖和Go编译器,可以利用docker来实现。 应该是解决起来话费时间最小的。
1. 用文本编辑你的go代码,现在以hello world为例:
 
package main import "fmt" func main() {
/* 这是我的第一个简单的程序 */
fmt.Println("Hello, World!")
}

 
2. 然后直接使用docker执行编译。docker首先会自动去下载go的编译器,顺便把所有的依赖给解决掉

docker run --rm -v "$(pwd)":/usr/src/hello -w /usr/src/hello golang:1.3 go build -v
 
最后会在本地生成一个编译好的hello静态文件。
上述docker命令的具体含义就是把当前路径挂在到docker容器里头,然后切换到改到改路径下,然后进行编译。

收起阅读 »

docker实战 代码勘误

作者在官网刊登的勘误记录:
 
看这本书的作者一定要看,不然坑挺多的。
一路采坑过来的哭着说。
Last updated August 21, 2016
In an effort to offer continued support beyond publication, we have listed many updates to code due to version updates.

[code - omission] Page 18

The command to start the "mailer" is missing a line. Where the book reads:
docker run -d \
--name mailer \
the proper command should read:
docker run -d \
--name mailer \
dockerinaction/ch2_mailer

[code - regression] Page 68

Newer versions of Docker have changed the structure of the JSON returned by the docker inspect subcommand. If the following command does not work then use the replacement. Original:
docker inspect --format "{{json .Volumes}}" reader
Replacement:
docker inspect --format "{{json .Mounts}}" reader

[code - regression] Page 69

Newer versions of Docker have changed the structure of the JSON returned by the docker inspect subcommand. If the following command does not work then use the replacement. Original:
docker inspect --format "{{json .Volumes}}" student
Replacement:
docker inspect --format "{{json .Mounts}}" student

[code - regression] Page 74

The alpine image entrypoint has changed since original publication and has been unset. The last command on the page should now read:
docker run --rm \
--volumes-from tools \
--entrypoint /bin/sh \
alpine:latest \
-c 'ls /operations/*'
[code - regression] Page 75

The docker exec example on the top of page 75 was printed with the wrong tool name. The correct command is:
docker exec important_application /operations/tools/diagnostics

[code - regression] Page 86

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--hostname barker \
busybox:1 \
nslookup barker

[code - regression] Page 87 (top)

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--dns 8.8.8.8 \
busybox:1 \
nslookup docker.com

[code - regression] Page 87 (bottom)

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--dns-search docker.com \
busybox:1 \
nslookup registry.hub

[code - regression] Page 88 (bottom)

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--add-host test:10.10.10.255 \
busybox:1 \
nslookup test

[code - regression] Page 106

There are a few new problems with this example. First, the named repository (dockerfile/mariadb) no longer exists. You can use mariadb:5.5 as replacement. However, the second problem is that containers created from the mariadb image perform certain initialization at startup. That initialization work requires certain capabilities and to be started with the default user. The system should instead drop permissions after the initialization work is complete. Note that the real value of this example is in demonstrating different resource isolation mechanisms. It is not so important that you get it working. You can start the database with the following command:
docker run -d --name ch6_mariadb \
--memory 256m \
--cpu-shares 1024 \
--cap-drop net_raw \
-e MYSQL_ROOT_PASSWORD=test \
mariadb:5.5

[code - regression] Page 107

Containers created from the wordpress:4.1 image perform certain initialization at startup and expect certain environment variables. That initialization work requires certain capabilities and to be started with the default user. The system should instead drop permissions after the initialization work is complete. Note that the real value of this example is in demonstrating different resource isolation mechanisms. It is not so important that you get it working. You can start wordpress with the following command:
docker run -d -P --name ch6_wordpress \
--memory 512m \
--cpu-shares 512 \
--cap-drop net_raw \
-e WORDPRESS_DB_PASSWORD=test \
mariadb:5.5

[code - typo] Page 109

The device access example is missing the "run" subcommand. The command listed as:
docker -it --rm \
--device /dev/video0:/dev/video0 \
ubuntu:latest ls -al /dev
should have been written as:
docker run -it --rm \
--device /dev/video0:/dev/video0 \
ubuntu:latest ls -al /dev

[code - typo] Page 110 - 111

Several commands are missing the "run" subcommand. In each case the command begins with
docker -d ...
and should have been written as:
docker run -d ...

[code - regression] Page 115 (bottom)

The busybox and alpine images have been updated to fix the problem described in the paragraph below. The 'su' command does not have the SUID bit set and will not provide any automatic privilege escalation.

[command correction] Page 116

Boot2Docker has been discontinued and rolled into a newer project called Docker Machine. Because a reader is unlikely to have the boot2docker command installed, the command at the top of this page should be changed from:
boot2docker ssh
to the Docker Machine equivalent:
docker-machine ssh default
where default is the name of the machine you created.

[code - regression] Page 119

The ifconfig command has since been removed from ubuntu:latest. Instead of using the ubuntu:latest image for these examples use ubuntu:trusty. The example using ifconfig should look like:
docker run --rm \
--privileged \
ubuntu:trusty ifconfig
[Illustration Mistake] Page 136
Image layer ced2 on the left side of the illustration is listed at c3d2 on the right side. These two layers should represent the same item.

[code - typo] Page 140

Containers need not be in a running state in order to export their file system. The first command on page 140 uses the "run" subcommand but the command listed will never be able to start. Replace "run" with "create." The command should appear as follows:
docker create --name export-test \
dockerinaction/ch7_packed:latest ./echo For Export

[code - missing line] Page 146

In the example Dockerfile near the top of the page the line with the RUN directive is missing part of the instruction. That line should read:
RUN apt-get update && apt-get install -y git

[code - evolution] Page 215

The registry:2 configuration file now requires the population of additional fields under "maintenance > uploadpurging." The example should currently look like:
# Filename: s3-config.yml
version: 0.1
log:
level: debug
fields:
service: registry
environment: development
storage:
cache:
layerinfo: inmemory
s3:
accesskey:
secretkey:
region:
bucket:
encrypt: true
secure: true
v4auth: true
chunksize: 5242880
rootdirectory: /s3/object/name/prefix
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
http:
addr: :5000
secret: asecretforlocaldevelopment
debug:
addr: localhost:5001

[code - evolution] Page 216

The registry:2 configuration file now requires the population of additional fields under "maintenance > uploadpurging." The example should currently look like:
# Filename: rados-config.yml
version: 0.1
log:
level: debug
fields:
service: registry
environment: development
storage:
cache:
layerinfo: inmemory
rados:
poolname: radospool
username: radosuser
chunksize: 4194304
maintenance:
uploadpurging:
enabled: false
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
http:
addr: :5000
secret: asecretforlocaldevelopment
debug:
addr: localhost:5001

[code - evolution] Page 218

The registry:2 configuration file now requires the population of additional fields under "maintenance > uploadpurging." The example should currently look like:
# Filename: redis-config.yml
version: 0.1
log:
level: debug
fields:
service: registry
environment: development
http:
addr: :5000
secret: asecretforlocaldevelopment
debug:
addr: localhost:5001
storage:
cache:
blobdescriptor: redis
s3:
accesskey:
secretkey:
region:
bucket:
encrypt: true
secure: true
v4auth: true
chunksize: 5242880
rootdirectory: /s3/object/name/prefix
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
redis:
addr: redis-host:6379
password: asecret
dialtimeout: 10ms
readtimeout: 10ms
writetimeout: 10ms
pool:
maxidle: 16
maxactive: 64
idletimeout: 300s
[code - typo] Page 220

The name of the file shown should be scalable-config.yml as in previous examples. This example also requires the addition of the newer uploadpurging attributes. The mainenance section of the file should be as follows:
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
[text - typo] Page 240

In the second paragraph the reader is instructed to, "Open ./coffee/api/api.py" this is not the correct location of the file. The correct file location is at, "./coffee/app/api.py."
[text - typo] Page 262

The refere nce to "flock.json" in the first sentence of the third paragraph should be "flock.yml."
[code - typo] Page 270

The git clone command uses the ssh protocol instead of https. The command should read as follows:
git clone https://github.com/dockerinact ... i.git
继续阅读 »
作者在官网刊登的勘误记录:
 
看这本书的作者一定要看,不然坑挺多的。
一路采坑过来的哭着说。
Last updated August 21, 2016
In an effort to offer continued support beyond publication, we have listed many updates to code due to version updates.

[code - omission] Page 18

The command to start the "mailer" is missing a line. Where the book reads:
docker run -d \
--name mailer \
the proper command should read:
docker run -d \
--name mailer \
dockerinaction/ch2_mailer

[code - regression] Page 68

Newer versions of Docker have changed the structure of the JSON returned by the docker inspect subcommand. If the following command does not work then use the replacement. Original:
docker inspect --format "{{json .Volumes}}" reader
Replacement:
docker inspect --format "{{json .Mounts}}" reader

[code - regression] Page 69

Newer versions of Docker have changed the structure of the JSON returned by the docker inspect subcommand. If the following command does not work then use the replacement. Original:
docker inspect --format "{{json .Volumes}}" student
Replacement:
docker inspect --format "{{json .Mounts}}" student

[code - regression] Page 74

The alpine image entrypoint has changed since original publication and has been unset. The last command on the page should now read:
docker run --rm \
--volumes-from tools \
--entrypoint /bin/sh \
alpine:latest \
-c 'ls /operations/*'
[code - regression] Page 75

The docker exec example on the top of page 75 was printed with the wrong tool name. The correct command is:
docker exec important_application /operations/tools/diagnostics

[code - regression] Page 86

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--hostname barker \
busybox:1 \
nslookup barker

[code - regression] Page 87 (top)

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--dns 8.8.8.8 \
busybox:1 \
nslookup docker.com

[code - regression] Page 87 (bottom)

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--dns-search docker.com \
busybox:1 \
nslookup registry.hub

[code - regression] Page 88 (bottom)

It appears that nslookup behavior in the alpine image has changed. To run the example use the busybox:1 image.
docker run --rm \
--add-host test:10.10.10.255 \
busybox:1 \
nslookup test

[code - regression] Page 106

There are a few new problems with this example. First, the named repository (dockerfile/mariadb) no longer exists. You can use mariadb:5.5 as replacement. However, the second problem is that containers created from the mariadb image perform certain initialization at startup. That initialization work requires certain capabilities and to be started with the default user. The system should instead drop permissions after the initialization work is complete. Note that the real value of this example is in demonstrating different resource isolation mechanisms. It is not so important that you get it working. You can start the database with the following command:
docker run -d --name ch6_mariadb \
--memory 256m \
--cpu-shares 1024 \
--cap-drop net_raw \
-e MYSQL_ROOT_PASSWORD=test \
mariadb:5.5

[code - regression] Page 107

Containers created from the wordpress:4.1 image perform certain initialization at startup and expect certain environment variables. That initialization work requires certain capabilities and to be started with the default user. The system should instead drop permissions after the initialization work is complete. Note that the real value of this example is in demonstrating different resource isolation mechanisms. It is not so important that you get it working. You can start wordpress with the following command:
docker run -d -P --name ch6_wordpress \
--memory 512m \
--cpu-shares 512 \
--cap-drop net_raw \
-e WORDPRESS_DB_PASSWORD=test \
mariadb:5.5

[code - typo] Page 109

The device access example is missing the "run" subcommand. The command listed as:
docker -it --rm \
--device /dev/video0:/dev/video0 \
ubuntu:latest ls -al /dev
should have been written as:
docker run -it --rm \
--device /dev/video0:/dev/video0 \
ubuntu:latest ls -al /dev

[code - typo] Page 110 - 111

Several commands are missing the "run" subcommand. In each case the command begins with
docker -d ...
and should have been written as:
docker run -d ...

[code - regression] Page 115 (bottom)

The busybox and alpine images have been updated to fix the problem described in the paragraph below. The 'su' command does not have the SUID bit set and will not provide any automatic privilege escalation.

[command correction] Page 116

Boot2Docker has been discontinued and rolled into a newer project called Docker Machine. Because a reader is unlikely to have the boot2docker command installed, the command at the top of this page should be changed from:
boot2docker ssh
to the Docker Machine equivalent:
docker-machine ssh default
where default is the name of the machine you created.

[code - regression] Page 119

The ifconfig command has since been removed from ubuntu:latest. Instead of using the ubuntu:latest image for these examples use ubuntu:trusty. The example using ifconfig should look like:
docker run --rm \
--privileged \
ubuntu:trusty ifconfig
[Illustration Mistake] Page 136
Image layer ced2 on the left side of the illustration is listed at c3d2 on the right side. These two layers should represent the same item.

[code - typo] Page 140

Containers need not be in a running state in order to export their file system. The first command on page 140 uses the "run" subcommand but the command listed will never be able to start. Replace "run" with "create." The command should appear as follows:
docker create --name export-test \
dockerinaction/ch7_packed:latest ./echo For Export

[code - missing line] Page 146

In the example Dockerfile near the top of the page the line with the RUN directive is missing part of the instruction. That line should read:
RUN apt-get update && apt-get install -y git

[code - evolution] Page 215

The registry:2 configuration file now requires the population of additional fields under "maintenance > uploadpurging." The example should currently look like:
# Filename: s3-config.yml
version: 0.1
log:
level: debug
fields:
service: registry
environment: development
storage:
cache:
layerinfo: inmemory
s3:
accesskey:
secretkey:
region:
bucket:
encrypt: true
secure: true
v4auth: true
chunksize: 5242880
rootdirectory: /s3/object/name/prefix
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
http:
addr: :5000
secret: asecretforlocaldevelopment
debug:
addr: localhost:5001

[code - evolution] Page 216

The registry:2 configuration file now requires the population of additional fields under "maintenance > uploadpurging." The example should currently look like:
# Filename: rados-config.yml
version: 0.1
log:
level: debug
fields:
service: registry
environment: development
storage:
cache:
layerinfo: inmemory
rados:
poolname: radospool
username: radosuser
chunksize: 4194304
maintenance:
uploadpurging:
enabled: false
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
http:
addr: :5000
secret: asecretforlocaldevelopment
debug:
addr: localhost:5001

[code - evolution] Page 218

The registry:2 configuration file now requires the population of additional fields under "maintenance > uploadpurging." The example should currently look like:
# Filename: redis-config.yml
version: 0.1
log:
level: debug
fields:
service: registry
environment: development
http:
addr: :5000
secret: asecretforlocaldevelopment
debug:
addr: localhost:5001
storage:
cache:
blobdescriptor: redis
s3:
accesskey:
secretkey:
region:
bucket:
encrypt: true
secure: true
v4auth: true
chunksize: 5242880
rootdirectory: /s3/object/name/prefix
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
redis:
addr: redis-host:6379
password: asecret
dialtimeout: 10ms
readtimeout: 10ms
writetimeout: 10ms
pool:
maxidle: 16
maxactive: 64
idletimeout: 300s
[code - typo] Page 220

The name of the file shown should be scalable-config.yml as in previous examples. This example also requires the addition of the newer uploadpurging attributes. The mainenance section of the file should be as follows:
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
[text - typo] Page 240

In the second paragraph the reader is instructed to, "Open ./coffee/api/api.py" this is not the correct location of the file. The correct file location is at, "./coffee/app/api.py."
[text - typo] Page 262

The refere nce to "flock.json" in the first sentence of the third paragraph should be "flock.yml."
[code - typo] Page 270

The git clone command uses the ssh protocol instead of https. The command should read as follows:
git clone https://github.com/dockerinact ... i.git
收起阅读 »