西维蜀黍

【Redis】Redis 常用命令

Redis中的所有数据结构均不支持数据类型的嵌套。比如,集合类型的每个元素都只能是字符串,而不能是另一个集合或散列表(Hash)。

字符串(String)

SET - 插入数据

SET key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX] [GET]
  • Time complexity: O(1)

Set key to hold the string value. If key already holds a value, it is overwritten, regardless of its type.

如果当前 key 已经存在 value,则用新 value 覆盖原有的value值。

一旦设置成功(无论当前有没有发生覆盖),则返回OK;如果没设置成功,返回 nil (比如 options中包含了 nx,这时,只有当当前 key 不存在 value时,才会真正去设置value,即无覆盖发生。否则,就会返回 nil)。

Return Value

  • Simple string reply: OK if SET was executed correctly.
  • Null reply: a Null Bulk Reply is returned if the SET operation was not performed because the user specified the NX or XX option but the condition was not met.

Options

The SET command supports a set of options that modify its behavior:

  • EX seconds – Set the specified expire time, in seconds.

  • PX milliseconds – Set the specified expire time, in milliseconds.

  • NX – Only set the key if it does not already exist.

    127.0.0.1:6379> set a cc
    OK
    127.0.0.1:6379> set a cccc
    OK
    127.0.0.1:6379> set a ddd NX
    (nil)
    
  • XX – Only set the key if it already exist.

  • KEEPTTL – Retain the time to live associated with the key.

  • GET – Return the old value stored at key, or nil when key did not exist.

GET - 读数据

  • Time complexity: O(1)

Get the value of key. If the key does not exist the special value nil is returned. An error is returned if the value stored at key is not a string, because GET only handles string values.

即,如果当前key没有value值,则返回null

GETSET key value

  • Time complexity: O(1)

将键 key 的值设为 value , 并返回键 key 在被设置之前的旧值。

返回值

返回给定键 key 的旧值。

如果键 key 没有旧值, 也即是说, 键 key 在被设置之前并不存在, 那么命令返回 nil 。

当键 key 存在但不是字符串类型时, 命令返回一个错误。

APPEND - 数据追加

  • 如果当前key的value有值则附加到原有string后面,如果没有则写入。返回值为追加后的数据长度

DEL - 数据删除

  • Time complexity: O(N) where N is the number of keys that will be removed. When a key to remove holds a value other than a string, the individual complexity for this key is O(M) where M is the number of elements in the list, set, sorted set or hash. Removing a single key that holds a string value is O(1).

Removes the specified keys. A key is ignored if it does not exist.

Return value

Integer reply: The number of keys that were removed.

127.0.0.1:6379> set name wei
OK
127.0.0.1:6379> get name
"wei"
127.0.0.1:6379> append name isgreat
(integer) 10
127.0.0.1:6379> get name
"weiisgreat"
127.0.0.1:6379> del wei
(integer) 0
127.0.0.1:6379> get wei
(nil)
  ...


【Redis】安装 Redis

Via docker

$ mkdir redis_config; touch redis_config/redis.conf
$ docker run -itd --restart unless-stopped --name redis -p 6379:6379 redis

Access from another host

redis-cli -h 192.168.18.129
192.168.18.129:6379> ping
PONG
192.168.18.129:6379>

macOS 安装

Installation - Via brew

$ brew install redis

后台运行 redis 服务

$ brew services start redis

前台运行 Redis 服务

$ redis-server

可以直接运行 redis-server 以启动 Redis 服务(在服务端中输入 quit 可以退出)。然后另外开一个终端,运行 redis-cli 以启动一个客户端。

  ...


【Python】PyCharm 中的 import 问题

Problem

已经在 Terminal 下执行:

$ pip install django-redis

在项目中引用from django_redis import get_redis_connection。

但是在 PyCharm 中运行 Django,提示依赖包未安装错误:

ImportError: No module named redis_cache

但是,在 Termical 下执行:

$ python manage.py runserver

可以正常运行 Django。

  ...


【Python】Basics - 函数返回值

Introduction

In Python, you can return multiple values by simply return them separated by commas.

As an example, define a function that returns a string and a number as follows: Just write each value after the return, separated by commas.

def test():
    return 'abc', 100
  ...


【Python】Exception

try-except

try:
    raise FError("自定义异常")
except FError as e:
    print(e)

自定义异常

class ObjectNotExistInDBError(Exception):
    def __init__(self,msg):
        super(ObjectNotExistInDBError,self).__init__(self)
        self.msg=msg
    def __str__(self):
        return self.msg

抛出异常

主动抛出异常:

raise RuntimeError('testError')
  ...


【Django】Error - Django : Table doesn't exist

  ...


【Python】import

模块(Module)和包(Package)

为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。

使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。

如果不同的人编写的模块名相同怎么办?为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。

举个例子,一个abc.py的文件就是一个名字叫abc的模块,一个xyz.py的文件就是一个名字叫xyz的模块。

现在,假设我们的abc和xyz这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块,避免冲突。方法是选择一个顶层包名,比如mycompany,按照如下目录存放:

mycompany
├─ __init__.py
├─ abc.py
└─ xyz.py

引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。现在,abc.py模块的名字就变成了mycompany.abc,类似的,xyz.py的模块名变成了mycompany.xyz。

请注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany。

类似的,可以有多级目录,组成多级层次的包结构。比如如下的目录结构:

mycompany
 ├─ web
 │  ├─ __init__.py
 │  ├─ utils.py
 │  └─ www.py
 ├─ __init__.py
 ├─ abc.py
 └─ utils.py

文件www.py的模块名就是mycompany.web.www,两个文件utils.py的模块名分别是mycompany.utils和mycompany.web.utils。

自己创建模块时要注意命名,不能和Python自带的模块名称冲突。例如,系统自带了sys模块,自己的模块就不可命名为sys.py,否则将无法导入系统自带的sys模块。

Absolute Import

from src.packone import test1

绝对引用通过package的绝对路径引入module,且路径要从最上一层的package写起。

from xxx import *

# constants.py
MAX_ENTITY_NUMBER_LIMIT_FOR_DB_QUERY = 500
DEFAULT_ENTITY_NUMBER_FOR_DB_QUERY = 50

def a():
	pass

如果通过from core.constants import *,则 core.constants(对应constants.py文件)中定义的所有变量和函数,都可以在 views.py 中直接使用(无需通过 constants.MAX_ENTITY_NUMBER_LIMIT_FOR_DB_QUERY 来调用,就好像把constants.py文件全文复制到了views.py 中)

#views.py
from core.constants import *

def get_limit(l):
		a()
    if l is None:
        l = DEFAULT_ENTITY_NUMBER_FOR_DB_QUERY
    else:
        if l > MAX_ENTITY_NUMBER_LIMIT_FOR_DB_QUERY:
            l = DEFAULT_ENTITY_NUMBER_FOR_DB_QUERY
    return l
  ...


【Django】Django 读写 Cookie

获取Cookie

request.COOKIES[key]
request.COOKIES.get(key)
# 普通cookie是明文传输的,可以直接在客户端直接打开,所以需要加盐,解盐之后才能查看
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

参数:

  • default: 默认值
  • salt: 加密盐
  • max_age: 后台控制过期时间
  ...


【HTTP】Cookie

用途

因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么,所以Cookie就是用来绕开HTTP的无状态性的“额外手段”之一。服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。

在刚才的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段Cookie,记录着那项商品的信息。当用户访问另一个页面,浏览器会把Cookie发送给服务器,于是服务器知道他之前选购了什么。用户继续选购饮料,服务器就在原来那段Cookie里追加新的商品信息。结帐时,服务器读取发送来的Cookie就行了。

Cookie另一个典型的应用是当登录一个网站时,网站往往会请求用户输入用户名和密码,并且用户可以勾选“下次自动登录”。如果勾选了,那么下次访问同一网站时,用户会发现没输入用户名和密码就已经登录了。这正是因为前一次登录时,服务器发送了包含登录凭据(用户名加密码的某种加密形式)的Cookie到用户的硬盘上。第二次登录时,如果该Cookie尚未到期,浏览器会发送该Cookie,服务器验证凭据,于是不必输入用户名和密码就让用户登录了。

  ...


【Python】Collection - set

Set

Sets are a recent addition to the language that are neither mappings nor sequences; rather, they are unordered collections of unique and immutable objects. You create sets by calling the built-in set function or using new set literals and expressions in 3.X and 2.7, and they support the usual mathematical set operations (the choice of new {…} syntax for set literals makes sense, since sets are much like the keys of a valueless dic-tionary):

>>> X = set('spam')														# Make a set out of a sequence in 2.X and 3.X
>>> Y = {'h', 'a', 'm'}												# Make a set with set literals in 3.X and 2.7

>>> X, Y 																			# A tuple of two sets without parentheses 
({'m', 'a', 'p', 's'}, {'m', 'a', 'h'})

>>> X & Y 																		# Intersection 
{'m', 'a'}
>>> X | Y 																		# Union 
{'m', 'h', 'a', 'p', 's'}
>>> X - Y 																		# Difference
  ...