挖坑待填
[golang] map 与 sync.Map
[python] ValueError: IV must be 16 bytes long
书面
在
日志.
今天在研究 python 的 Crypto.Cipher 库中 AES 加密算法怎么使用,照着样例随手写了段代码,在执行时遇到以下问题:
ValueError: IV must be 16 bytes long
折腾了好一会儿都没搞定,上网看到有个大神也遇到过相同的问题,发现是在调用 AES.new 函数时参数iv 没填或不正确导致,正确的调用方法如下:
from Crypto.Cipher import AES from Crypto import Random key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" mode = AES.MODE_CBC iv = bytearray(AES.block_size) cryptor = AES.new(key, mode, iv) ...
或者直接把 iv 设置成
b'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
*注意千万不要填充
b'0000000000000000'
因为其实填充的是:
import binascii binascii.hexlify(b'0000000000000000') '30303030303030303030303030303030'
本文链接:/2018/11/30/python-valueerror-iv-must-be-16-bytes-long/
请尊重作者的劳动成果,转载请注明出处!Sakishum 博客保留对文章的所有权利。
The Best Hash Algorithm : BKDRHash
作者是
发布于
在
日志.
// BKDR Hash Function unsigned int BKDRHash(char *str) { unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. unsigned int hash = 0; while (*str) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF); }
本文链接:/2018/11/11/best-hash-function-algorithm-bkdrhash/
请尊重作者的劳动成果,转载请注明出处!Sakishum 博客保留对文章的所有权利。
解决MacOS升级后出现xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun的问题
作者是
发布于
在
日志.
今天升级macOS Mojave,终端里使用 brew update 的时候,弹出一行莫名其妙的错误:
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun Error: Failure while executing; `git config --local --replace-all homebrew.analyticsmessage true` exited with 1.
解决方法,重装xcode command line:
xcode-select --install
如果没有解决问题,执行以下命令:
sudo xcode-select -switch /
本文链接:/2018/10/23/macosxcrun-error-invalid-active-developer-path-librarydevelopercommandlinetools-missing-xcrun/
请尊重作者的劳动成果,转载请注明出处!Sakishum 博客保留对文章的所有权利。
[Spark] MySQL 踩坑记录
作者是
发布于
在
日志.
scala代码实现连接mysql
首先在 sbt 配置文件里添加:
"mysql" % "mysql-connector-java" % "8.0.12",
踩到的坑
1
使用 JDBC 访问特定数据库时,需要在 spark classpath 上添加对应的 JDBC 驱动配置。
--driver-class-path lib/mysql-connector-java-8.0.12.jar
不然代码在本地 sbt run 运行是没有问题, 但是放在服务器上用 spark-submit 提交的话,可能会报异常:
com.mysql.jdbc.Driver
2
运行项目中提示:
The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
'com.mysql.jdbc.Driver' 驱动类被弃用了,新的驱动类是 'com.mysql.cj.jdbc.Driver'。 这个驱动会通过 SPI 的方式自动加载,通常不需要人工手动加载。
val pool = MysqlConnectionPool(dbHost, dbUser, dbPasswd, "com.mysql.cj.jdbc.Driver")
本文链接:/2018/08/14/spark-mysql/
请尊重作者的劳动成果,转载请注明出处!Sakishum 博客保留对文章的所有权利。
[Django] 将 Django 的用户认证系统登陆界面替换成 Adminlte 主题
作者是
发布于
在
日志.
背景简介
最近在完善之前开发的 Django 管理系统,期间有使用 Adminlte 主题替换 Django 项目中用户认证系统登陆界面默认主题,并且效果好不错,特此记录下来以供日后使用。
为了更清楚地描述步骤,所以不会引入其他第三方的库,最大限度的利用 Django 提供的基础功能。
开发前,假设 Django 已经被安装,Adminlte 已经被下载(/path/to/ adminlte)。
相关资料
-
网站通常都会提供登录、注册、注销等用户认证功能。因此,Django 提供了一套功能完整的、灵活的、易于拓展的用户认证系统:django.contrib.auth。
-
Adminlte 是一个成熟的基于bootstrap的后台模板,下载地址
环境与版本说明
- OS: CentOS 7
- Python: 2.7
- Django: 1.11.0
- AdminLTE: 2.4.3
创建一个 Django 项目
$ django-admin startproject mysite
$ cd mysite/
修改 Django 项目中的文件
mysite/settings.py
ALLOWED_HOSTS = ['0.0.0.0',] # 修改 # ...(略过不表)... TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates'),], # 修改 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] # ...(略过不表)... # 添加以下代码 STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static"), ] LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/'
mysite/views.py
# 添加以下代码 from django.shortcuts import render from django.http import HttpResponse from django.conf import settings from django.contrib.auth.decorators import login_required @login_required def index(request): return render(request, 'index.html') mysite/urls.py from django.conf.urls import url from django.contrib import admin from . import views # 添加 from django.contrib.auth import views as auth_views # 添加 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', views.index, name='index'), # 添加 url(r'^login/', auth_views.login, { 'template_name': 'login.html' }, name='login'), # 添加 url(r'^logout/', auth_views.logout_then_login, name='logout'), # 添加 ]
创建管理员(admin)用户
$ python manage.py createsuperuser Username (leave blank to use 'username'): admin Email address: ****** Password: ****** Password (again): Superuser created successfully.
引入 Adminlte 模板文件
$ mkdir templates $ mkdir static $ cp /path/to/AdminLTE/pages/examples/login.html templates/ $ cp /path/to/AdminLTE/pages/examples/blank.html templates/index.html $ cp /path/to/AdminLTE/dist static/ $ cp /path/to/AdminLTE/bootstrap static/ $ cp /path/to/AdminLTE/plugins static/
修改相关 HTML 文件
template/login.html
{% load static %} <!-- 添加 --> <!DOCTYPE html> <!-- 以下是变更的地方 --> <!-- Bootstrap 3.3.6 --> <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}"> <!-- Theme style --> <link rel="stylesheet" href="{% static 'dist/css/AdminLTE.min.css' %}"> <!-- iCheck --> <link rel="stylesheet" href="{% static 'plugins/iCheck/square/blue.css' %}"> <div class="login-box-body"> {% if form.errors %} <!-- 添加 --> <p class="login-box-msg bg-red">Your username and password didn't match. Please try again.</p> <!-- 添加 --> {% else %} <!-- 添加 --> <p class="login-box-msg">Sign in to start your session</p> {% endif %} <!-- 添加 --> <form action="{% url 'login' %}" method="post"> {% csrf_token %} <!-- 添加 --> <input type="text" class="form-control" name="username" placeholder="Username"> <input type="password" class="form-control" name="password" placeholder="Password"> <!-- jQuery 2.2.3 --> <script src="{% static 'plugins/jQuery/jquery-2.2.3.min.js' %}"></script> <!-- Bootstrap 3.3.6 --> <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script> <!-- iCheck --> <script src="{% static 'plugins/iCheck/icheck.min.js' %}"></script>
template/index.html
{% load static %} <!-- 添加 --> <!DOCTYPE html> <!-- 以下是变更的地方 --> <!-- Bootstrap 3.3.6 --> <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}"> <!-- Theme style --> <link rel="stylesheet" href="{% static 'dist/css/AdminLTE.min.css' %}"> <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. --> <link rel="stylesheet" href="{% static 'dist/css/skins/_all-skins.min.css' %}"> <img src="{% static 'dist/img/user2-160x160.jpg' %}" class="img-circle" alt="User Image"> <img src="{% static 'dist/img/user2-160x160.jpg' %}" class="user-image" alt="User Image"> <img src="{% static 'dist/img/user2-160x160.jpg' %}" class="img-circle" alt="User Image"> <a href="{% url 'logout' %}" class="btn btn-default btn-flat">Sign out</a> <img src="{% static 'dist/img/user2-160x160.jpg' %}" class="img-circle" alt="User Image"> <!-- jQuery 2.2.3 --> <script src="{% static 'plugins/jQuery/jquery-2.2.3.min.js' %}"></script> <!-- Bootstrap 3.3.6 --> <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script> <!-- SlimScroll --> <script src="{% static 'plugins/slimScroll/jquery.slimscroll.min.js' %}"></script> <!-- FastClick --> <script src="{% static 'plugins/fastclick/fastclick.js' %}"></script> <!-- AdminLTE App --> <script src="{% static 'dist/js/app.min.js' %}"></script>
目录结构
mysite/ ├── manage.py ├── mysample │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── templates │ └── index.html ├── static │ ├── dist │ ├── bootstrap │ └── plugins └── mysite ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ └── settings.cpython-36.pyc ├── settings.py ├── urls.py └── wsgi.py
运行项目
$ python manage.py runserver 0.0.0.0:8080
打开浏览器并输入到“http://服务器IP:8080”,登录页面就出来了。
输入用户名“admin”和对应的密码,初始页面就会出现。
从初始画面点击“sign out”(登出),就会跳转到注销登录的页面。
以上
本文链接:/2018/07/13/django-django-adminlte/
请尊重作者的劳动成果,转载请注明出处!Sakishum 博客保留对文章的所有权利。
[Golang] 优雅地重启 go 服务
作者是
发布于
在
日志.
[Python]: 记一次使用 python 字典踩到的坑
作者是
发布于
在
日志.
问题背景
最近在使用 python 做一个数据量很大的统计任务,抽取账号相同的记录,进行统计并排序。代码中使用到了字典,存储账号相关的记录,用账号作为键。
key = msg_id.split("_")[0] if key not in alerm_date_dict: data = nbClientData() data.name = key data.succ = cnt_succ_client data.fail = cnt_fail_client alerm_date_dict[key] = data else: alerm_date_dict[key].succ += cnt_succ_client alerm_date_dict[key].fail += cnt_fail_client
包含以上代码的脚本跑了一个小时才把数据全部跑完,很是耗时,但是遍历数据并不应该是性能瓶颈,而且使用 python 的字典存取数据也并不慢, 但就是跑了整整一小时才跑完,是可忍孰不可忍。Stack Overflow 了一下, 原来罪魁祸首是这句代码导致的。
if key not in alerm_date_dict:
问题分析
字典是Python中唯一内建的映射类型。字典中的值并没有特殊的顺序,但是都存储在一个特点的键(key)里。键可以是数字、字符串甚至是元组。用过 python 的朋友都应该了解,判断一个 key 在不在字典或者列表里,使用 in 这个方法挺好用的。
按理说,python 的字典是C语言实现的 哈希表,效率应该不低才对。研究了一阵才发现隐藏了个坑,原来在对字典使用 in 的时候调用的是 dict.keys() 这个函数, 这个函数返回的是一个列表。
>>> newdict = {1:0, 2:0, 3:0} >>> newdict.keys() [1, 2, 3]
返回的列表包含了是整个字典的所有键,每次循环都返回十几万的数据,还要在列表里找对应的键,难怪那么慢!
解决办法
找到原因后,修改代码如下:
key = msg_id.split("_")[0] if alerm_date_dict.get(key) != None: data = nbClientData() data.name = key data.succ = cnt_succ_client data.fail = cnt_fail_client alerm_date_dict[key] = data else: alerm_date_dict[key].succ += cnt_succ_client alerm_date_dict[key].fail += cnt_fail_client
Python 字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值。直接操作字典,不会调用 dict.keys(),改完之后执行一两分钟就跑完任务了。
以上
本文链接:/2018/06/25/python/
请尊重作者的劳动成果,转载请注明出处!Sakishum 博客保留对文章的所有权利。
Golang:开源库 Go-MySQL-Driver 使用
作者是
发布于
在
日志.
A MySQL-Driver for Go's database/sql package
MySQL
MySQL is the world's most popular open source database. Whether you are a fast growing web property, technology ISV or large enterprise, MySQL can cost-effectively help you deliver high performance, scalable database applications. —— MySQL
MySQL驱动 Go-MySQL-Driver 使用
github 地址
文档
安装
$ go get -u github.com/go-sql-driver/mysql
导入
import "database/sql" import _ "github.com/go-sql-driver/mysql"
数据库表结构
USE test; CREATE TABLE `squareNum` ( `number` INT(11) NOT NULL DEFAULT '0', `squareNumber` INT(11) NOT NULL DEFAULT '0', PRIMARY KEY (`number`) ); /* +--------------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+---------+------+-----+---------+-------+ | number | int(11) | NO | PRI | NULL | | | squareNumber | int(11) | NO | | NULL | | +--------------+---------+------+-----+---------+-------+ */
用例
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "root:11111111@/test?charset=utf8") checkErr(err) defer db.Close() // Open doesn't open a connection. Validate DSN data: err = db.Ping() checkErr(err) // Use the DB normally, execute the querys etc stmtIns, err := db.Prepare("INSERT INTO squareNum VALUES( ?, ? )") checkErr(err) defer stmtIns.Close() // Close the statement when we leave main() / the program terminates stmtOut, err := db.Prepare("SELECT squareNumber FROM squareNum WHERE number = ?") checkErr(err) defer stmtOut.Close() for i := 0; i < 25; i++ { _, err = stmtIns.Exec(i, (i * i)) // Insert tuples (i, i^2) if err != nil { panic(err.Error()) // proper error handling instead of panic in your app } } var squareNum int // we "scan" the result in here // Query the square-number of 13 err = stmtOut.QueryRow(13).Scan(&squareNum) // WHERE number = 13 checkErr(err) fmt.Printf("The square number of 13 is: %d\n", squareNum) // Query another number.. 1 maybe? err = stmtOut.QueryRow(1).Scan(&squareNum) // WHERE number = 1 checkErr(err) fmt.Printf("The square number of 1 is: %d\n", squareNum) stmtIns, err = db.Prepare("DELETE FROM squareNum where number=?") checkErr(err) res, err := stmtIns.Exec(13) checkErr(err) affect, err := res.RowsAffected() checkErr(err) fmt.Println("affect:", affect) } func checkErr(err error) { if err != nil { panic(err.Error()) } } /* Output: The square number of 13 is: 169 The square number of 1 is: 1 affect: 1 */
以上
本文链接:/2018/06/21/golang-go-mysql-driver/
请尊重作者的劳动成果,转载请注明出处!Sakishum 博客保留对文章的所有权利。
Golang: 开源库 go-redis 使用
作者是
发布于
在
日志.
Redis
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. —— redis
开源库 go-redis 使用
github地址
文档
安装
go get -u github.com/go-redis/redis
导入
import "github.com/go-redis/redis"
用例
package main import ( "fmt" "github.com/go-redis/redis" ) func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", Password: "11111111", // no password set DB: 0, // use default DB }) pong, err := client.Ping().Result() if err != nil { panic("Connect fail!") } fmt.Println(pong) err = client.Set("key", "value", 0).Err() if err != nil { panic(err) } val, err := client.Get("key").Result() if err != nil { panic(err) } fmt.Println("key", val) val2, err := client.Get("key2").Result() if err == redis.Nil { fmt.Println("key2 does not exist") } else if err != nil { panic(err) } else { fmt.Println("key2", val2) } // Output: key value // key2 does not exist }