/images/avatar.jpeg

Python CookBook

platform

import platform

# 获取操作系统的位数
print('architecture: ', platform.architecture()) # architecture:  ('64bit', 'ELF')
# 计算机类型/CPU架构
print('machine: ', platform.machine()) # machine:  x86_64 aarch64
print('system:', platform.system()) # Linux
# 获取Linux内核版本
print('platform: ', platform.platform()) # Linux-5.4.0-42-generic-x86_64-with-glibc2.29
print('version: ', platform.version()) # #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020
# 计算机的网络名称
print('node: ', platform.node()) # idea570
# 计算机处理器信息
print('processor', platform.processor()) # processor x86_64
print('uname: ', platform.uname()) # uname_result(system='Linux', node='idea570', release='5.4.0-42-generic', version='#46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020', machine='x86_64', processor='x86_64')

print(platform.python_build()) # ('default', 'Jul 16 2020 14:00:26')
print(platform.python_compiler()) # GCC 9.3.0
print(platform.python_branch())
# python 解释器实现
print(platform.python_implementation()) # CPython
print(platform.python_revision())
print(platform.python_version_tuple()) # ('3', '8', '2')

lsb_release

import lsb_release
lsb_info = lsb_release.get_distro_information()
print(lsb_info) # {'ID': 'Ubuntu', 'DESCRIPTION': 'Ubuntu 20.04.1 LTS', 'RELEASE': '20.04', 'CODENAME': 'focal'}
print('ID: ', lsb_info.get('ID')) # ID:  Ubuntu
print('RELEASE: ', lsb_info.get('RELEASE')) # RELEASE:  20.04
print('DESCRIPTION: ', lsb_info.get('DESCRIPTION')) # DESCRIPTION: 'Ubuntu 20.04.1 LTS
print('CODENAME: ', lsb_info.get('CODENAME')) # CODENAME:  focal

密码哈希

from passlib.apps import custom_app_context as pwd_context
password = pwd_context.encrypt('password')
print(password, len(password))
# $6$rounds=656000$Q.AXo68BhIXq7LnM$bldegF6rHZ5Gi7ujPnXHOAdnAvC8srNImdIFQ9DcBWx7aF0sCWn/HryRIbyh6nuyhD3Trp.y2Sb6yVEyHsWCS1 120

result = pwd_context.verify('password', password)
print(result)   # True

selenium 登陆测试

import time
from selenium import webdriver
browser = webdriver.Firefox(executable_path='/opt/geckodriver')
browser.get('http://127.0.0.1:8080')

name_input = browser.find_element_by_xpath("//*[@type='text']")  # 找到用户名的框框
pass_input = browser.find_element_by_xpath("//*[@type='password']")  # 找到输入密码的框框
login_button = browser.find_element_by_class_name('loginButton')  # 找到登录按钮

name_input.clear()
name_input.send_keys('admin')  # 填写用户名
time.sleep(0.2)
pass_input.clear()
pass_input.send_keys('password')  # 填写密码
time.sleep(0.2)
login_button.click()  # 点击登录

c = browser.context()
print(c)

删除字典值为空的元素

dict(filter(lambda x: x[1] != ‘’, dic.items()))

2017 计蒜之道 初赛 第一场 阿里的新游戏 题解

问题:

  • 阿里九游开放平台近日上架了一款新的益智类游戏——成三棋。成三棋是我国非常古老的一个双人棋类游戏.
  • 成三棋的棋盘上有很多条线段,只能在线段交叉点上放入棋子。我们可以用坐标系来描述棋盘.
  • 如果一条线段上的三个交叉点都被同一玩家的棋子占据的话,则称这条线段被该玩家 成三。现在,小红和小明两人在游戏平台上下棋,其中小红的棋子是黑色的。请你帮小红计算他成三的线段数。
  • 样例对应的棋盘如下: /20170728-2017%E8%AE%A1%E8%92%9C%E4%B9%8B%E9%81%93%E5%88%9D%E8%B5%9B%E7%AC%AC%E4%B8%80%E5%9C%BA%E9%98%BF%E9%87%8C%E7%9A%84%E6%96%B0%E6%B8%B8%E6%88%8F%E9%A2%98%E8%A7%A3/three_chess.jpg
输入
  • 输入第一行两个整数 (n,m(3 \le n, m \le 9)),n表示小红的棋子数,m表示小明的棋子数。
  • 接下来 n行输入小红的棋子坐标。
  • 接下来 m行输入小明的棋子坐标。
  • 输入保证坐标合法,并且棋子之间不重合。
6 3
-1 0
-2 0
-3 0
-1 -1
-1 1
1 0
0 2
0 3
2 2
样例输出
# 输出小红成三的线段数。
2
题解
  • 按一定规则对成三棋盘进行扫描,应避免某些坐标点漏扫或重复扫描.
x ,y = [int(x) for x in str(input()).split()]
R = []
for m in range(x):
    mx,my = [int(x) for x in str(input()).split()]
    R.append(tuple((mx,my)))

num = 0

for x in range(-3,4):
    if len(set(R) & set([(x,0)])) > 0:
        # 正方形竖边
        if (x,x) in R and (x,-x) in R:
            num += 1
        # X正半轴
        if x==2 and (x+1,0) in R and (x-1,0) in R:
            num += 1
        # X负半轴
        if x==-2 and (x+1,0) in R and (x-1,0) in R:
            num += 1

    if len(set(R) & set([(0,x)])) > 0:
        # 正方形横边
        if (x,x) in R and (-x,x) in R:
            num += 1
        # Y正半轴
        if x == 2 and (0, x+1) in R and (0, x-1) in R:
            num += 1
        # Y负半轴
        if x == -2 and (0, x+1) in R and (0, x-1) in R:
            num += 1

print(num)

使用lxml提取HTML/XML 数据

demo

#更新: 新版本引入etree模块方式

from lxml import html
etree = html.etree
tree = etree.HTML("")
html = '''
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title class="sub_title">Title</title>
</head>
<body>
<div class="none">
<a href ="#">Spaceack's code</a>
</div>
<div class="link">
<a href ="http://spaceack.com">Spaceack's blog</a>
</div>
</body>
</html>
'''

from lxml import etree
tree = etree.HTML(html)
# 获取class为link的a标签的元素内容
a_content = tree.xpath('.//div[@class="link"]/a/text()')
print(a_content)
# ["Spaceack's blog"]

# 使用attrib获取标签的属性值
href_element = tree.xpath('.//div[@class="link"]/a')
print(href_element)
# [<Element a at 0x7ff3571a4d80>]
href = href_element[0].attrib.get('href')
print(href)
# http://spaceack.com

获取标签元素内容为空的两种不同效果:

  • demo
from lxml import etree
# 可见第二个标签 td 元素内容为空
tree = etree.HTML("<th>水果</th><td>苹果</td><th>价格</th><td></td>")
key = tree.xpath("//th/text()")
value = tree.xpath("//td/text()")
print(key, value)
'''
['水果', '价格'] ['苹果']
'''

如果想让价格使用None或空字符串''来占位,可以这样做:

Java学习笔记-基本程序设计结构

Java 文档下载

使用集成开发环境

Eclipse

新建项目

  1. File-New-Project
  2. 对话框中选择Java Project

配置eclipse工程.png

  1. 点击Finish

Virtual Studio Code

  1. 安装扩展包Java Extension Pack
  2. Ctrl-Shift-D 根据提示生成launch.json配置文件
  3. F5运行程序

第一段Java程序

// Welcome/Welcome.java
public class Welcome{
    public static void main(String [] args){
        String greeting = "Welcome to Spaceack's blog";
        System.out.println(greeting);
        for(int i=0; i<greeting.length(); i++)
            System.out.print("=");
        System.out.println();
    } 
}

程序解读

  1. 关键字public称为访问修饰符(access modifier)用于控制程序其它部分对这段代码的访问级别。

Django-通过示例定制admin后台管理

后台管理改为中文

#  将 setting.py  配置选项设置为中文
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'

LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'

/20160305-djangoadmin%E6%89%A9%E5%B1%95/%E6%9B%B4%E6%96%B0%E5%89%8D.png

/20160305-djangoadmin%E6%89%A9%E5%B1%95/%E6%9B%B4%E6%96%B0%E5%90%8E.png

更改后台标题和名称(title/header)

# admin.py 文件添加 修改网页title和站点header
admin.site.site_header = 'XXX平台-管理系统'
admin.site.site_title = 'XXX平台'

/20160305-djangoadmin%E6%89%A9%E5%B1%95/%E5%90%8E%E5%8F%B0%E6%A0%87%E9%A2%98.png

Django常用配置-setting.py 模板

DATABASES 模板

## DATABASES

### sqlite3
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

### mysql
DATABASES = { 
    'default': { 
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'mydb', #数据库名称(需要先创建) 
        'USER': 'root', # 数据库用户名 
        'PASSWORD': '123456', # 数据库密码 
        'HOST': '', # 数据库主机,留空默认为localhost 
        'PORT': '3306', # 数据库端口 
        } 
    }

### Postgresql

DATABASES = { 
    'default': { 
        'ENGINE': 'django.db.backends.postgresql_psycopg2', 
        'NAME': 'mydb', # 数据库名字(需要先创建) 
        'USER': 'postgres', # 登录用户名 
        'PASSWORD': '123456', # 密码 
        'HOST': '', # 数据库IP地址,留空默认为localhost 
        'PORT': '5432', # 端口 
        } 
    }
    

Internationalization 模板

LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'

Static files 配置模板

STATIC_URL = '/static/'
MEDIA_URL =  '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

LOGGING 模板

BASE_LOG_DIR = os.path.join(BASE_DIR, "log")
LOGGING = {
    'version': 1,  # 保留字
    'disable_existing_loggers': False,  # 禁用已经存在的logger实例
    # 日志文件的格式
    'formatters': {
        # 详细的日志格式
        'standard': {
            'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
                      '[%(levelname)s][%(message)s]'
        },
        # 简单的日志格式
        'simple': {
            'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
        },
        # 定义一个特殊的日志格式
        'collect': {
            'format': '%(message)s'
        }
    },
    # 过滤器
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    # 处理器
    'handlers': {
        # 在终端打印
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],  # 只有在Django debug为True时才在屏幕打印日志
            'class': 'logging.StreamHandler',  #
            'formatter': 'simple'
        },
        # 默认的
        'default': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"),  # 日志文件
            'maxBytes': 1024 * 1024 * 50,  # 日志大小 50M
            'backupCount': 3,  # 最多备份几个
            'formatter': 'standard',
            'encoding': 'utf-8',
        },
        # 专门用来记错误日志
        'error': {
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"),  # 日志文件
            'maxBytes': 1024 * 1024 * 50,  # 日志大小 50M
            'backupCount': 5,
            'formatter': 'standard',
            'encoding': 'utf-8',
        },
        # 专门定义一个收集特定信息的日志
        'collect': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
            'maxBytes': 1024 * 1024 * 50,  # 日志大小 50M
            'backupCount': 5,
            'formatter': 'collect',
            'encoding': "utf-8"
        }
    },
    'loggers': {
       # 默认的logger应用如下配置
        '': {
            'handlers': ['default', 'console', 'error'],  # 上线之后可以把'console'移除
            'level': 'DEBUG',
            'propagate': True,  # 向不向更高级别的logger传递
        },
        # 名为 'collect'的logger还单独处理
        'collect': {
            'handlers': ['console', 'collect'],
            'level': 'INFO',
        }
    },
}

CKEDITOR_5 模板

CKEDITOR_5_CUSTOM_CSS = 'path_to.css'  # optional
CKEDITOR_5_CONFIGS = {
    'default': {
        'toolbar': ['heading', '|', 'bold', 'italic', 'link',
                    'bulletedList', 'numberedList', 'blockQuote', 'imageUpload', ],

    },
    'extends': {
        'blockToolbar': [
            'paragraph', 'heading1', 'heading2', 'heading3',
            '|',
            'bulletedList', 'numberedList',
            '|',
            'blockQuote', 'imageUpload'
        ],
        'toolbar': ['heading', '|', 'outdent', 'indent', '|', 'bold', 'italic', 'link', 'underline', 'strikethrough',
                    'code', 'subscript', 'superscript', 'highlight', '|',
                    'bulletedList', 'numberedList', 'todoList', '|', 'blockQuote', 'imageUpload', '|',
                    'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor', 'mediaEmbed', 'removeFormat',
                    'insertTable', ],
        'image': {
            'toolbar': ['imageTextAlternative', 'imageTitle', '|', 'imageStyle:alignLeft', 'imageStyle:full',
                        'imageStyle:alignRight', 'imageStyle:alignCenter', 'imageStyle:side', '|'],
            'styles': [
                'full',
                'side',
                'alignLeft',
                'alignRight',
                'alignCenter',
            ]

        },
        'table': {
            'contentToolbar': ['tableColumn', 'tableRow', 'mergeTableCells']
        },
        'heading': {
            'options': [
                {'model': 'paragraph', 'title': 'Paragraph', 'class': 'ck-heading_paragraph'},
                {'model': 'heading1', 'view': 'h1', 'title': 'Heading 1', 'class': 'ck-heading_heading1'},
                {'model': 'heading2', 'view': 'h2', 'title': 'Heading 2', 'class': 'ck-heading_heading2'},
                {'model': 'heading3', 'view': 'h3', 'title': 'Heading 3', 'class': 'ck-heading_heading3'}
            ]
        }
    }
}

Linux 网络

centos系 网卡配置路径

`/etc/sysconfig/network-scripts/`
  • 配置示列 ifcfg-enp0s3
    TYPE=Ethernet
    PROXY_METHOD=none
    BROWSER_ONLY=no
    BOOTPROTO=static
    DEFROUTE=yes
    IPV4_FAILURE_FATAL=no
    IPV6INIT=yes
    IPV6_AUTOCONF=yes
    IPV6_DEFROUTE=yes
    IPV6_FAILURE_FATAL=no
    IPV6_ADDR_GEN_MODE=stable-privacy
    NAME=enp0s3
    UUID=xxxxxx-xxxx-xxxx-xxxx-xxxxxxx
    DEVICE=enp0s3
    ONBOOT=yes
    IPADDR=192.168.0.200
    PREFIX=24
    GATEWAY=192.168.0.1
    DNS1=8.8.8.8
    IPV6_PRIVACY=no
    • BOOTPROTO 静态IP(static) or 动态IP(dhcp)
    • ONBOOT 网卡随系统启动激活
    • PREFIX 新版本Linux 配置子网掩码的参数 等价于 NETMASK NETMASK=255.255.255.0 重启网络服务 systemctl restart network

ubuntu系 网卡配置路径

17.10 后 废弃

/etc/network/interfaces

Linux切换jdk默认版本

  1. 安装多个jdk版本

sudo yum install java-1.8.0-openjdk-devel

sudo yum install java-11-openjdk-devel

  1. 查看当前默认版本 java -version

  2. 切换默认版本 sudo alternatives --config java

Linux 常用命令

系统篇

# 查看LBS 发行版本
cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"
# 查看系统有哪些shell
cat /etc/shell
# 创建用户spaceack; 生成home目录 /home/spaceack ; 指定默认使用zsh
sudo adduser --home /home/spaceack --shell /usr/bin/zsh spaceack
# 用户给予sudo权限, 直接加入sudo组
sudo usermod -aG sudo spaceack
# 其它实现方法
sudo useradd -d /home/spaceack -s /bash/zsh spaceack

linux 查询进程所在目录

# 找到进程id
ps -aux | grep xxx
ll /proc/进程pid

lsof -p 进程pid

CPU

lscpu
cat /proc/cpuinfo
# 查看CPU架构
uname -a | awk '{print $12}'

内存

# 查看主板内存插槽数及使用情况
dmidecode|grep -P -A 5 "Memory\s+Device" | grep Size|grep -v Range

# 查看主板支持最大内存
sudo dmidecode | grep -P 'Maximum\s+Capacity'

# 查看内存频率
sudo dmidecode | grep -A16 "Memory Device"|grep 'Speed'

# 查看内存及交换空间使用情况
# -h 以 Gibibytes为单位查看.
free -m

磁盘 df

# 查看目录的剩余空间, 本质是查看该目录挂载的磁盘的剩余空间。 默认是千字节。
ubuntu@primary:~$ df /tmp
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda1        4911436 2261092   2633960  47% /
# -T显示磁盘分区类型
ubuntu@primary:~$ df -T /tmp
Filesystem     Type 1K-blocks    Used Available Use% Mounted on
/dev/sda1      ext4   4911436 2265444   2629608  47% /

# 配合管道命令 sed awk。 提取 某个数值,如可用空间(Available)
ubuntu@primary:~$ df /tmp| sed '1d' | awk '{print $4}'
2629608

# -i 查看 inode 的使用情况
ubuntu@primary:~$ df -i /tmp
Filesystem     Inodes  IUsed  IFree IUse% Mounted on
/dev/sda1      648320 137952 510368   22% /

快速删除大量文件

# 创建空目录
mkdir /tmp/empty/
# 使用 rsync 快速删除 /data/logs/ 目录下文件
rsync --delete-before -d /tmp/empty/ /data/logs/
# 删除空目录
rmdir /tmp/empty/

禁用某个目录的写入权限

chattr +i /tmp/empty/

交换分区

查看类型为 swap 的 交换分区名称