python

python 类型转换

  • int to binary

    >>> bin(6)
    '0b110'
    >>> bin(6)[2:]
    '110'
    
  • binary to int

    >>> int('11111111', 2)
    255
    
    >>> from bitstring import BitArray
    >>> b = Bitarray(bin='11111111')
    >>> b.uint
    255
    >>> b.int
    -1
    

import 问题

python 中 import 其它模块时,如果路径不对,会出现找不到模块的错误。 假设代码目录结构如下:

-- src
   |-- m1.py
   |-- mod2
   |     `-- m2.py
   |-- mod3
   |     `-- m3.py
   `-- main.py
  • 主程序与模块在同一级目录

    main.py import m1.py

    import m1
    
  • main.py 中 import m2.py

    我们先试试直接 import, 则会报 ImportError: No module named .. 错误。

    >>> import mod2.m2
    ImportError: No module named mod2.m2
    

    这是因为 python 只会把有 __init__.py 文件的目录当做 python package. 在 mod2 目录下添加 __init__.py 文件, 此时目录结构如下:

    -- src
       |-- m1.py
       |-- mod2
       |     |-- __init__.py
       |     `-- m2.py
       |-- mod3
       |     |-- __init__.py
       |     `-- m3.py
       `-- main.py
    

    此时再 import 就不会出错了。

    >>> import mod2.m2
    

    这里我们运行下面的代码看看:

    >>> import mod2
    >>> dir(mod2)
    ['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']
    

    我们可以看到这里 dir 函数并没有打印 m2.py, 是不是感觉 比较奇怪,其实这里 import 只是导入了 mod2.__init__.py 如果我们希望 dir(mod2) 能看到 m2.py 里的函数,我们需要在 __init__.py 中 import m2

  • m2 import m3

    这种情况比较复杂, 如果程序的入口是 m2.py , 那么导入方式如下:

    import sys
    sys.append('..')
    import m3
    

    如果程序的入口是 main.py 然后在 main.py 用到了m2, 那么导入方式如下:

    import mod1.m1
    

python json 处理

解析 json 数据

解析 json 分为两种,一种是解析 json 字符串, 另一种是解析 json 文件

  1. 解析 json 字符串

    >>> import json
    
    >>> json_str = '{"name": "lina", "age": 23}'
    >>> json_obj = json.loads(json_str)
    
    >>> print json_obj
    {u'age': 23, u'name': u'lina'}
    
  2. 解析 json 文件

    import json
    
    with open('json_file_path') as fp:
        json_obj = json.load(fp)
    
    # or use loads
    json_obj = json.loads(open('json_file_path').read())
    

转化为 json 字符串

  1. 转为为 json 字符串

    import json
    
    json_obj = {u'age': 23, u'name': u'lina'}
    json_str = json.dumps(json_obj)
    

try 模块

python 中有一个 try..except..else 的组合。光看 try..except 跟其它语言查不多,可是为什么要加一个 else呢?

如果 except 没有捕获到异常,就会执行 else 部分的代码。既然不在 except 中执行,为什么不直接放到 try 语句中呢?这是因为如果我们 指定了 except 的类型,当出现其它 except 时,并不能捕获,所以就 走 else 流程了。需要注意的是,正常执行 try 语句之后也会执行 else 代码。

shell

grep 使用

sed 使用

awk 使用

文件目录操作

  • 获取脚本所在路径

    export SCRIPT_HOME=$(dirname $(readlink -f $0))
    

openstack

cloud-init 介绍

cloud-init 是一个系统配置工具,当系统起来时, cloud-init 会从固定分区读取数据,然后执行定制化 操作。

cloud-init 有四个执行阶段:

  • local: cloud-init-local.service
  • init: cloud-init.service
  • config: cloud-config.service
  • final: cloud-final.service

配置

cloud-init 各阶段完成哪些工作可以在 /etc/cloud/cloud.cfg 中查看

  1. local 阶段

    作为 cloud-init 的初始阶段,此时主要完成网口的配置

    /usr/bin/cloud-init init --local

  2. init 阶段

  3. config 阶段

  4. final 阶段

cloud-init 脚本生成

社区提供了 write-mime-multipart 工具来生成 cloud-init 脚本。 使用方法如下:

$ cat my-boothook.txt
#!/bin/sh
echo "Hello World!"
echo "This will run as soon as possible in the boot sequence"

$ cat my-user-script.txt
#!/usr/bin/perl
print "This is a user script (rc.local)\n"

$ cat my-include.txt
# these urls will be read pulled in if they were part of user-data
# comments are allowed.  The format is one url per line
http://www.ubuntu.com/robots.txt
http://www.w3schools.com/html/lastpage.htm

$ cat my-upstart-job.txt
description "a test upstart job"
start on stopped rc RUNLEVEL=[2345]
console output
task
script
echo "====BEGIN======="
echo "HELLO From an Upstart Job"
echo "=====END========"
end script

$ cat my-cloudconfig.txt
#cloud-config
ssh_import_id: [smoser]
apt_sources:
 - source: "ppa:smoser/ppa"

$ write-mime-multipart --output=combined-userdata.txt \
    my-boothook.txt:text/cloud-boothook \
    my-include.txt:text/x-include-url \
    my-upstart-job.txt:text/upstart-job \
    my-user-script.txt:text/x-shellscript \
    my-cloudconfig.txt

User Data 输入格式

  1. Gzip Compressed Content

  2. Mime Multi Part archive

  3. User-Data Script

    #!Content-Type: text/x-shellscript 开头。

    存放用户脚本,可以是 python, shell, perl 等。user data 里的脚本执行比较晚,类似 rc.local, 而且只在第一次启动时 执行。

  4. Include File

    #includeContent-Type: text/x-include-url 开头。

    includ file 的内容是一串 url, 每行一个,cloud-init 启动时会 读取 url 链接的内容。

  5. Cloud Config Data

    #cloud-configContent-Type: text/cloud-config 开头, 内容按规定格式编写。

  6. Upstart Job

    #upstart-jobContent-Type: text/upstart-job 开头,

    文件内容会存放在 /etc/init ,以供其它 job 使用。

  7. Cloud Boothook

    #cloud-boothookContent-Type: text/cloud-boothook 开头。

    boothook 数据会保存到 /var/lib/cloud ,然后立刻执行。boothook 每次上电都会执行,没有机制指定只运行一次。

  8. Part Handler

BFV

ipxe 介绍

ipxe 是 pxe 的扩展,提供了如下功能:

  • boot from a web server via HTTP
  • boot from an iSCSI SAN
  • boot from a Fibre Channel SAN via FCoE
  • boot from an AoE SAN
  • boot from a wireless network
  • boot from a wide-area network
  • boot from an Infiniband network
  • control the boot process with a script

ipxe 使用

使用 ipxe 有两种方式:

  • 使用 ipxe 固件替换网卡的 PXE ROM
  • 使用链式启动来加载 ipxe 固件

ipxe 可以从: http://boot.ipxe.org/ipxe.iso 下载, 但是要想使用 ipxe 的全部功能,建议通过源码自己编译。 编译方法如下:

git clone git://git.ipxe.org/ipxe.git
cd ipxe/src
make

编译

  1. 编译成 iso

    make bin/ipxe.iso
    
  2. 编译成 usb

    make bin/ipxe.usb
    dd if=bin/ipxe.usb of=/dev/sdX
    
  3. 编译成 pxe rom 的链式加载文件

    make bin/undionly.kpxe
    
  4. 替代现有 PXE ROM

    make bin/808610de.rom
    

ironic 使用 ipxe

  1. 创建 http 根目录

    mkdir -p /tftpboot
    mkdir -p /httpboot
    chown -R ironic /tftpboot
    chown -R ironic /httpboot
    
  2. 设置 tftp map file

    echo 'r ^([^/]) /tftpboot/\1' > /tftpboot/map-file
    echo 'r ^(/tftpboot/) /tftpboot/\2' >> /tftpboot/map-file
    
  3. 配置 tftp 和 http server

    [pxe]
    tftp_root=/tftpboot
    tftp_server=192.168.0.2
    ipxe_enabled=True
    
    [deploy]
    http_root=/httpboot
    http_url=http://192.168.0.2:8080
    
  4. 配置 http 服务器

    这里以 apacha 为例,如果使用 nginx 请参考 nginx 的配置方法。

    • 安装 httpd
    $ sudo yum install httpd
    
    • 配置 httpd

    修改 /etc/httpd/conf/httpd.conf

    <Directory />
        Options Indexes FollowSymLinks
        AllowOverride none
    </Directory>
    
    DocumentRoot "/httpboot"
    
    • 重启服务
    $ sudo systemctl restart httpd
    
  5. 设置 ipxe 模板

    [pxe]
    pxe_bootfile_name=undionly.kpxe
    pxe_config_template = $pybasedir/drivers/modules/ipxe_config.template
    
  6. 安装 iPXE 相关包

    yum install ipxe-bootimgs
    cp /usr/share/ipxe/{undionly.kpxe,ipxe.efi} /tftpboot
    
  7. 重启 conductor 服务

    sudo systemctl restart openstack-ironic-conductor
    

rabbitmq

介绍

rabbitmq 是消息处理的中间人,可以类比现实生活中的邮局。

术语

  • 生产者

    发送消息的程序叫生产者。

  • 消费者

    接收消息的程序称为消费者。

  • 消息队列

    消息队列驻留在 rabbitmq 中,用来存放消息,理论上消息队列大小 无限制,实际上跟机器的内存和硬盘大小有关。

生产者消费者模型

大部分情况下生成者,消费者,消息队列都在不同的机器上。我们先看一个 hello world 的例子。

模型如下图:

_images/python-one-overall.png

生产者代码:

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='hello')

channel.basic_publish(exchange='',
                  routing_key='hello',
                  body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()

消费者代码:

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='hello')

def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)

channel.basic_consume(callback,
                      queue='hello',
                      no_ack=True)

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

RPC 模型

call 方法

cctxt = self.client.prepare(topic=topic or self.topic, version='1.22')
cctxt.call(context, 'do_node_deploy', node_id=node_id,
           rebuild=rebuild, configdrive=configdrive)

cast 方法

OS

SUSE

源配置

使用 yast 进入图形化配置,然后添加如下源

SQL

常用sql

逻辑运算

sql 中用 ORAND 来表示条件的

$ SELECT * FROM World;
+-----------------+------------+------------+--------------+---------------+
| name            | continent  | area       | population   | gdp           |
+-----------------+------------+------------+--------------+---------------+
| Afghanistan     | Asia       | 652230     | 25500100     | 20343000      |
| Albania         | Europe     | 28748      | 2831741      | 12960000      |
| Algeria         | Africa     | 2381741    | 37100000     | 188681000     |
| Andorra         | Europe     | 468        | 78115        | 3712000       |
| Angola          | Africa     | 1246700    | 20609294     | 100990000     |
+-----------------+------------+------------+--------------+---------------+

$ SELECT name,population,area FROM World WHERE area > 3000000 OR population > 25000000;
+--------------+-------------+--------------+
| name         | population  | area         |
+--------------+-------------+--------------+
| Afghanistan  | 25500100    | 652230       |
| Algeria      | 37100000    | 2381741      |
+--------------+-------------+--------------+

分组统计

$ SELECT * FROM Person;
+----+---------+
| Id | Email   |
+----+---------+
| 1  | a@b.com |
| 2  | c@d.com |
| 3  | a@b.com |
+----+---------+

$ SELECT Email FROM Person GROUP BY Email having count(Email) > 1;
+---------+
| Email   |
+---------+
| a@b.com |
+---------+

English

常用词汇

  • redundant: 多余的
  • jargon: 术语

Indices and tables