-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
738 lines (550 loc) · 890 KB
/
atom.xml
File metadata and controls
738 lines (550 loc) · 890 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>陈凡的个人站点</title>
<subtitle>chenfanlinux.org</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://www.chenfanlinux.org/"/>
<updated>2019-07-02T10:46:14.000Z</updated>
<id>http://www.chenfanlinux.org/</id>
<author>
<name>陈凡</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>到底应该怎么理解平均负载</title>
<link href="http://www.chenfanlinux.org/2019/07/02/%E5%88%B0%E5%BA%95%E5%BA%94%E8%AF%A5%E6%80%8E%E4%B9%88%E7%90%86%E8%A7%A3%E5%B9%B3%E5%9D%87%E8%B4%9F%E8%BD%BD/"/>
<id>http://www.chenfanlinux.org/2019/07/02/到底应该怎么理解平均负载/</id>
<published>2019-07-02T08:43:38.000Z</published>
<updated>2019-07-02T10:46:14.000Z</updated>
<content type="html"><![CDATA[<h4 id="1、如何了解系统的平均负载"><a href="#1、如何了解系统的平均负载" class="headerlink" title="1、如何了解系统的平均负载"></a>1、如何了解系统的平均负载</h4><blockquote><p>每次发现系统变慢时,我们通常做的第一件事,就是执行 top,或者 uptime 命令,来了解系统的负载情况。比如像下面这样,我在命令行里输入了 uptime 命令,系统负载情况。</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@bogon ~]<span class="comment"># uptime</span></span><br><span class="line"> 15:20:35 up 3:44, 4 users, load average: 0.00, 0.01, 0.05</span><br></pre></td></tr></table></figure><p>我相信你对前面的几列比较熟悉,它们分别是当前时间、系统运行时、以及正在登录用户数。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> 15:20:35 // 当前时间</span><br><span class="line"> up 3:44 // 系统运行时间</span><br><span class="line"> 4 users // 当前登录用户数</span><br><span class="line">load average: 0.00, 0.01, 0.05 // 过去1分钟、5分钟、15分钟的负载数</span><br></pre></td></tr></table></figure><h4 id="2、什么是平均负载?"><a href="#2、什么是平均负载?" class="headerlink" title="2、什么是平均负载?"></a>2、什么是平均负载?</h4><p>它是最常见也是最重要的系统指标。简单来说,平均负载时是单位时间内,系统处于<strong>可运行</strong>及<strong>不可中断</strong>状态的平均进程数,也就是<strong>平均活跃进程数</strong>。所以,它不仅包括了<strong>正在使用CPU的进程</strong>,还包括了<strong>等待CPU</strong>和<strong>等待I/O</strong>的进程。和CPU使用率没有直接关系。</p><ul><li><strong>可运行状态的进程:</strong> 是指正在使用CPU或者正在等待CPU的进程。也就是我们用ps命令看到处于R状态的进程。 </li><li><strong>不可中断状态的进程:</strong> 是指哪些处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的I/O响应,也就说我们用ps看到处于D状态(Uninterruptible Sleep,也称为 Disk Sleep) 的进程。这其实是系统对进程和硬件设备的一种保护机制。</li></ul><a id="more"></a><h4 id="3、平均负载为多少时合理"><a href="#3、平均负载为多少时合理" class="headerlink" title="3、平均负载为多少时合理"></a>3、平均负载为多少时合理</h4><p>我们知道,平均负载最理想的情况是等于 CPU 个数。所以在评判平均负载时,首先你要知道系统有几个 CPU核心数,这可以这可以通过 top 命令或者从文件 /proc/cpuinfo中获取,比如</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grep <span class="string">'model name'</span> /proc/cpuinfo |wc -l <span class="comment"># 获取逻辑核心数</span></span><br></pre></td></tr></table></figure><p>有了 CPU 个数,我们就可以判断出,当平均负载比 CPU 个数还大的时候,系统已经出现了过载。不过,且慢,新的问题又来了。我们在例子中可以看到,平均负载有三个数值,到底该参考哪一个呢?</p><p>实际上,都要看。三个不同时间间隔的平均值,其实给我们提供了,分析系统负载趋势的数据来源,让我们能更全面和更立体地理解目前的负载状况。</p><ul><li>如果 1 分钟、5 分钟、15 分钟的三个值基本相同,或者相相差不大,那就说明系统负载很平稳。</li><li>但如果 1 分钟的值远小于 15 分钟的值,就说明系统最近 1 分钟的负载在减少,而过去 15 分钟内却有很大的负载。</li><li>反过来,如果 1 分钟的值远大于 15 分钟的值,就说明最近就说明最近 1 分钟的负载在增加,这种增加有可能只是临时性的也有可能还会持续增加下去,所以就需要持续观察。一旦 1 分钟的平均负载接近或超过了 CPU 的个数,就意味着系统正在发生过载的问题,这时就得分析调查是哪里导致的。</li></ul><p>那么,在实际生产环境中,平均负载多高时,需要我们重点关注呢?</p><p>在我看来,当平均负载高于 CPU 数量 70% 的时候,你就应该分析排查负载高的问题了。一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能。</p><p>但 70% 这个数字并不是绝对的,最推荐的方法,还是把系统的还是把系统的平均负载监控起来,然后根据更多的历史数据,判断负载的变化趋势。当发现负载有明显升高趋势时,比如说负载翻倍了,你再去做分析和调查。</p><h4 id="4-平均负载与-CPU-使用率"><a href="#4-平均负载与-CPU-使用率" class="headerlink" title="4.平均负载与 CPU 使用率"></a>4.平均负载与 CPU 使用率</h4><p>现实工作中,我们经常容易把平均负载和 CPU 使用率混淆,所以在这里,我也做一个区分。可能你会疑惑,既然平均负载代表的是活跃进程数,那平均负载高了。不就意味着 CPU 使用率高吗?</p><p>我们还是要回到平均负载的含义上来,平均负载是指单位时间内,处于<strong>可运行状态</strong>和<strong>不可中断状态</strong>的进程数。所以,它不仅包括了正在使用 CPU 的进程,还包括<strong>等待 CPU</strong> 和<strong>等待IO</strong>的进程。</p><p>而 CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应。比如:</p><ul><li>CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;</li><li>I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;</li><li>大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。</li></ul><h4 id="5-平均负载案例分析"><a href="#5-平均负载案例分析" class="headerlink" title="5. 平均负载案例分析"></a>5. 平均负载案例分析</h4><h5 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h5><ul><li>机器配置:centos 7.x 2 CPU,8GB 内存( 这个根据个人机器配置来)。</li><li>预先安装 stress和stress-ng 和 sysstat 1.5.5版本以后</li><li>sysstat工具介绍<ul><li>而 sysstat 包含了常用的 Linux 性能工具,用来用来监控和分析系统的性能。我们的案例会用到这个包的两个命令mpstat 和 pidstat。</li><li>mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标。</li><li>pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。</li></ul></li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># stress 压测工具</span></span><br><span class="line">yum install stress stress-ng -y </span><br><span class="line"></span><br><span class="line"><span class="comment"># systat 12.1.5 性能测试工具</span></span><br><span class="line">gcc -v</span><br><span class="line">rpm -e --nodeps sysstat</span><br><span class="line">wget http://pagesperso-orange.fr/sebastien.godard/sysstat-12.1.5.tar.gz</span><br><span class="line">tar xf sysstat-12.1.5.tar.gz</span><br><span class="line"><span class="built_in">cd</span> sysstat-12.1.5/</span><br><span class="line">./configure</span><br><span class="line">sa_lib_dir=/usr/lib/sa sa_dir=/var/<span class="built_in">log</span>/sa conf_dir=/etc/sysconfig ./configure --prefix=/usr --<span class="built_in">disable</span>-file-attr && make && make install</span><br></pre></td></tr></table></figure><h5 id="场景一:CPU-密集型进程"><a href="#场景一:CPU-密集型进程" class="headerlink" title="场景一:CPU 密集型进程"></a>场景一:CPU 密集型进程</h5><p>首先,我们在第一个终端运行 stress 命令,模拟一个 CPU 使用率 100% 的场景</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ stress --cpu 1 --timeout 600</span><br></pre></td></tr></table></figure><p>接着,在第二个终端运行 uptime 查看平均负载的变化情况</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -d 参数表示高亮显示变化的区域</span></span><br><span class="line">$ watch -d uptime</span><br><span class="line">load average: 1.00, 0.75, 0.39</span><br></pre></td></tr></table></figure><p>最后,在第三个终端运行 mpstat 查看 CPU 使用情况</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据</span></span><br><span class="line">$ mpstat -P ALL 5</span><br><span class="line">Linux 3.10.0-957.1.3.el7.x86_64 (bogon) 2019年07月02日 _x86_64_(1 CPU)</span><br><span class="line"></span><br><span class="line">15时52分06秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle</span><br><span class="line">15时52分11秒 all 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00</span><br><span class="line">15时52分11秒 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00</span><br></pre></td></tr></table></figure><p>从终端二中可以看到,1 分钟的平均负载会慢慢增加到 1.00, 而从终端三中还可以看到,正好有一个 CPU 的使用率为 10.一个 CPU 的使用率为 100%,但它的 iowait 但它的 iowait 只有 0。这说明,平均负载的升高正是由于 CPU 使用率为 100% 。</p><p>那么,到底是哪个进程导致了 CPU 使用率为 100% 呢?你可以使用 pidstat 来查询:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -u 5 间隔5秒, 20 输出20次结果</span></span><br><span class="line">$ pidstat -u 5 20</span><br><span class="line">Linux 3.10.0-957.1.3.el7.x86_64 (bogon) 2019年07月02日 _x86_64_(1 CPU)</span><br><span class="line"></span><br><span class="line">15时56分10秒 UID PID %usr %system %guest %<span class="built_in">wait</span> %CPU CPU Command</span><br><span class="line">15时56分15秒 0 9075 99.40 0.00 0.00 0.40 99.40 0 stress</span><br><span class="line">15时56分15秒 0 9231 0.00 0.20 0.00 0.00 0.20 0 pidstat</span><br></pre></td></tr></table></figure><p>从这里可以明显看到,stress 进程的 CPU 使用率为 100%</p><h5 id="场景二:I-O-密集型进程"><a href="#场景二:I-O-密集型进程" class="headerlink" title="场景二:I/O 密集型进程"></a>场景二:I/O 密集型进程</h5><p>首先还是运行 stress-ng 命令,但这次模拟 I/O。即不停地执行 sync</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># --hdd表示读写临时文件</span></span><br><span class="line">$ stress-ng -i 1 --hdd 1 --timeout 600</span><br></pre></td></tr></table></figure><p>接着,在第二个终端运行 uptime 查看平均负载的变化情况</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ watch -d uptime</span><br><span class="line">Every 2.0s: uptime Tue Jul 2 16:01:43 2019</span><br><span class="line"></span><br><span class="line"> 16:01:43 up 4:25, 4 users, load average: 0.91, 0.78, 0.48</span><br></pre></td></tr></table></figure><p>然后,第三个终端运行 mpstat 查看 CPU 使用率.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据</span></span><br><span class="line">$ mpstat -P ALL 5</span><br><span class="line">Linux 3.10.0-957.1.3.el7.x86_64 (bogon) 2019年07月02日 _x86_64_(1 CPU)</span><br><span class="line">16时01分57秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle</span><br><span class="line">16时02分02秒 all 0.21 0.00 9.13 90.46 0.00 0.21 0.00 0.00 0.00 0.00</span><br><span class="line">16时02分02秒 0 0.21 0.00 9.13 90.46 0.00 0.21 0.00 0.00 0.00 0.00</span><br></pre></td></tr></table></figure><p>从这里可以看到,1 分钟的平均负载会慢慢增加到 1点左右 , 其中一个 CPU 的系统 CPU 使用率升高到了 23.87, 而 iowait 高达 90.46%。这说明,平均负载的升高是由于 iowait 的升高。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ pidstat -d 5 20 <span class="comment"># 注意这里是-d 是磁盘指标</span></span><br><span class="line">16时10分51秒 UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command</span><br><span class="line">16时10分56秒 0 9588 0.00 0.00 0.00 540 kworker/u256:1</span><br><span class="line">16时10分56秒 0 10105 0.00 398758.40 26171.20 0 stress-ng</span><br><span class="line">16时10分56秒 0 10107 0.00 0.00 0.00 218 stress-ng-io</span><br></pre></td></tr></table></figure><p>可以发现,还是 stress-ng-hdd 进程导致的。</p><h5 id="场景三:大量进程的场景"><a href="#场景三:大量进程的场景" class="headerlink" title="场景三:大量进程的场景"></a>场景三:大量进程的场景</h5><p>当系统中运行进程超出 CPU 运行能力时,就会出现等待 CPU</p><p>比如,我们还是使用 stress,但这次模拟的是 8 个进程。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ stress -c 8 --timeout 600</span><br></pre></td></tr></table></figure><p>由于系统只有 1 个 CPU,明显比 8 个进程要少得多,因而,系统的 CPU 处于严重过载状态.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ watch -d uptime</span><br><span class="line">Every 2.0s: uptime Tue Jul 2 16:18:23 2019</span><br><span class="line"></span><br><span class="line"> 16:18:23 up 4:41, 4 users, load average: 2.93, 1.74, 1.07</span><br></pre></td></tr></table></figure><p>可以看到cpu使用率增加到很快100%。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ mpstat -P ALL 5</span><br><span class="line">16时19分00秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle</span><br><span class="line">16时19分05秒 all 99.60 0.00 0.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00</span><br><span class="line">16时19分05秒 0 99.60 0.00 0.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00</span><br></pre></td></tr></table></figure><p>接着再运行 pidstat 来看一下进程的情况:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 间隔 5 秒后输出一组数据,-u 表示 CPU 指标</span></span><br><span class="line">$ pidstat -u 5 20</span><br><span class="line">Linux 3.10.0-957.1.3.el7.x86_64 (bogon) 2019年07月02日 _x86_64_(1 CPU)</span><br><span class="line"></span><br><span class="line">16时20分09秒 UID PID %usr %system %guest %<span class="built_in">wait</span> %CPU CPU Command</span><br><span class="line">16时20分14秒 0 10603 12.35 0.00 0.00 87.06 12.35 0 stress</span><br><span class="line">16时20分14秒 0 10604 12.35 0.00 0.00 87.45 12.35 0 stress</span><br><span class="line">16时20分14秒 0 10605 12.35 0.00 0.00 86.67 12.35 0 stress</span><br><span class="line">16时20分14秒 0 10606 12.35 0.00 0.00 87.25 12.35 0 stress</span><br><span class="line">16时20分14秒 0 10607 12.35 0.00 0.00 86.27 12.35 0 stress</span><br><span class="line">16时20分14秒 0 10608 12.35 0.00 0.00 86.86 12.35 0 stress</span><br><span class="line">16时20分14秒 0 10609 12.16 0.00 0.00 85.49 12.16 0 stress</span><br><span class="line">16时20分14秒 0 10610 12.35 0.00 0.00 86.27 12.35 0 stress</span><br><span class="line">16时20分14秒 0 10679 0.00 0.20 0.00 0.00 0.20 0 pidstat</span><br></pre></td></tr></table></figure><p>可以看出,8 个进程在争抢 1 个 CPU,每个进程等待,每个进程等待 CPU 的时间(也就是代码块中的 %wait)高达 87%。这些超出 CPU 计算能力的进程, 最终导致 CPU 过载。</p><h4 id="6-小结"><a href="#6-小结" class="headerlink" title="6.小结"></a>6.小结</h4><p>平均负载提供了一个快速查看系统整体性能的手段,反映了整体的负载情况。但只看平均负载本身,我们并不能直接发,到底是哪里出现了瓶颈。所以,在理解平均负载时,也要注意:</p><ul><li>平均负载高有可能是 CPU 密集型进程导致的;</li><li>平均负载高并不一定代表 CPU 使用率高,还有可能是 I/O</li><li>当发现负载高的时候,你可以使用 mpstat、pidstat等工具,辅助分析负载的来源。</li><li></li></ul>]]></content>
<summary type="html">
<h4 id="1、如何了解系统的平均负载"><a href="#1、如何了解系统的平均负载" class="headerlink" title="1、如何了解系统的平均负载"></a>1、如何了解系统的平均负载</h4><blockquote>
<p>每次发现系统变慢时,我们通常做的第一件事,就是执行 top,或者 uptime 命令,来了解系统的负载情况。比如像下面这样,我在命令行里输入了 uptime 命令,系统负载情况。</p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@bogon ~]<span class="comment"># uptime</span></span><br><span class="line"> 15:20:35 up 3:44, 4 users, load average: 0.00, 0.01, 0.05</span><br></pre></td></tr></table></figure>
<p>我相信你对前面的几列比较熟悉,它们分别是当前时间、系统运行时、以及正在登录用户数。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> 15:20:35 // 当前时间</span><br><span class="line"> up 3:44 // 系统运行时间</span><br><span class="line"> 4 users // 当前登录用户数</span><br><span class="line">load average: 0.00, 0.01, 0.05 // 过去1分钟、5分钟、15分钟的负载数</span><br></pre></td></tr></table></figure>
<h4 id="2、什么是平均负载?"><a href="#2、什么是平均负载?" class="headerlink" title="2、什么是平均负载?"></a>2、什么是平均负载?</h4><p>它是最常见也是最重要的系统指标。简单来说,平均负载时是单位时间内,系统处于<strong>可运行</strong>及<strong>不可中断</strong>状态的平均进程数,也就是<strong>平均活跃进程数</strong>。所以,它不仅包括了<strong>正在使用CPU的进程</strong>,还包括了<strong>等待CPU</strong>和<strong>等待I/O</strong>的进程。和CPU使用率没有直接关系。</p>
<ul>
<li><strong>可运行状态的进程:</strong> 是指正在使用CPU或者正在等待CPU的进程。也就是我们用ps命令看到处于R状态的进程。 </li>
<li><strong>不可中断状态的进程:</strong> 是指哪些处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的I/O响应,也就说我们用ps看到处于D状态(Uninterruptible Sleep,也称为 Disk Sleep) 的进程。这其实是系统对进程和硬件设备的一种保护机制。</li>
</ul>
</summary>
<category term="linux性能优化" scheme="http://www.chenfanlinux.org/categories/linux%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/"/>
<category term="linux" scheme="http://www.chenfanlinux.org/tags/linux/"/>
</entry>
<entry>
<title>Helm一键部署k8s应用</title>
<link href="http://www.chenfanlinux.org/2019/03/15/Helm%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B2k8s%E5%BA%94%E7%94%A8/"/>
<id>http://www.chenfanlinux.org/2019/03/15/Helm一键部署k8s应用/</id>
<published>2019-03-15T15:42:04.000Z</published>
<updated>2019-03-15T15:53:42.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>Helm is the best way to find, share, and use software built for Kubernetes.</p></blockquote><p>Helm会通过读取Kubernetes配置文件(通常是$HOME/.kube/config)来找到安装Tiller的位置。这与kubectl使用的文件相同。要确定将把Tiller安装到哪个集群,可以运行kubectl配置current-context或kubectl cluster-info。</p><h3 id="安装Helm和安装Tiller"><a href="#安装Helm和安装Tiller" class="headerlink" title="安装Helm和安装Tiller"></a>安装Helm和安装Tiller</h3><h4 id="初始化Helm和安装Tiller"><a href="#初始化Helm和安装Tiller" class="headerlink" title="初始化Helm和安装Tiller"></a>初始化Helm和安装Tiller</h4><p>准备好Helm后,您可以初始化本地CLI,也可以一步将Tiller安装到Kubernetes集群中:。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ helm init</span><br></pre></td></tr></table></figure><p>这将把Tiller安装到您在kubectl配置当前上下文中看到的Kubernetes集群中。</p><a id="more"></a><h3 id="使用Helm管理k8s应用"><a href="#使用Helm管理k8s应用" class="headerlink" title="使用Helm管理k8s应用"></a>使用Helm管理k8s应用</h3><p><a href="http://helm.sh/" target="_blank" rel="noopener">Helm</a>是一个kubernetes应用的包管理工具,用来管理<a href="https://github.com/kubernetes/charts" target="_blank" rel="noopener">charts</a>——预先配置好的安装包资源,有点类似于Ubuntu的APT和CentOS中的yum。</p><p>Helm chart是用来封装kubernetes原生应用程序的yaml文件,可以在你部署应用的时候自定义应用程序的一些metadata,便与应用程序的分发。</p><p>Helm和charts的主要作用:</p><ul><li>应用程序封装</li><li>版本管理</li><li>依赖检查</li><li>便于应用程序分发</li></ul><h3 id="Helm常见命令总结"><a href="#Helm常见命令总结" class="headerlink" title="Helm常见命令总结"></a>Helm常见命令总结</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">1. 下载官方的chart文件</span><br><span class="line">https://github.com/helm/charts</span><br><span class="line">2. 推送本地的chart文件到远程仓库</span><br><span class="line">helm push ./sonarqube 37059-axd(可能需要安装push plugins)</span><br><span class="line">helm repo update</span><br><span class="line">3. 安装sonarqube release</span><br><span class="line">helm install 37059-axd/sonarqube --name sonar-test --namespace=default</span><br><span class="line">4. 本地更新release</span><br><span class="line">helm upgrade sonarqube ./sonarqube --namespace=default</span><br><span class="line">5. 测试安装</span><br><span class="line">helm install --dry-run --debug ./upsource</span><br><span class="line">helm install ./upsource --name upsource --namespace=default</span><br><span class="line">6. 渲染chart文件,得到资源清单文件</span><br><span class="line">helm template ./sonarqube</span><br><span class="line">7. 查看部署应用的资源使用</span><br><span class="line">kubectl top pod sonar-test-sonarqube-74fcdb4b4c-8zctv</span><br><span class="line">8. 回滚</span><br><span class="line">helm <span class="built_in">history</span> sonar-test</span><br><span class="line">helm rollback sonar-test 1</span><br><span class="line">9.移除指定 Release 所有相关的 Kubernetes 资源和 Release 的历史记录</span><br><span class="line">helm delete --purge sonar-test</span><br><span class="line">10. 如何在部署时指定命名空间?</span><br><span class="line">helm install <span class="built_in">local</span>/mychart --name mike-test --namespace mynamespace</span><br><span class="line">11.如何查看已部署应用的详细信息?</span><br><span class="line">helm get wordpress-test</span><br><span class="line">12. 本地模版渲染</span><br><span class="line">hlem template ./sonarqube</span><br><span class="line">13. 日志查看</span><br><span class="line">kubectl logs sonarqube-sonarqube-78f5d5b5db-6h8q7</span><br><span class="line">14. 重启某一名称空间的服务</span><br><span class="line">kubectl delete pods --all -n develop</span><br><span class="line">15. 强制更新某个名称空间的部署</span><br><span class="line">imageTag=v3.11.1</span><br><span class="line">helm upgrade --namespace=<span class="variable">$namespace</span> --<span class="built_in">set</span> image.tag=<span class="variable">$imageTag</span> aixiangdao-<span class="variable">${namespace}</span> 37059-axd/aixiangdao --force</span><br><span class="line"></span><br><span class="line">16. 更新部署配置</span><br><span class="line">helm upgrade --namespace=performance aixiangdao-performance ./aixiangdao-bak</span><br><span class="line"></span><br><span class="line">17 . 获取release的清单配置</span><br><span class="line">helm get aixiangdao-green</span><br><span class="line"></span><br><span class="line">18. helm依赖管理</span><br><span class="line">helm dependency update cert-manager</span><br><span class="line">helm dependency build</span><br><span class="line">这个命令会根据requirements.yaml文件中的依赖配置,找到项目底下依赖目录,将目录安装到charts目录下。</span><br><span class="line">不使用helm dependency update cert-manager</span><br><span class="line">直接让依赖项目放到charts 目录下。</span><br><span class="line"></span><br><span class="line">helm install --name=cert-manager --namespace=cert-manager ./cert-manager</span><br><span class="line">kubectl apply -f clusterissuers.yaml</span><br></pre></td></tr></table></figure><h3 id="创建自己的chart"><a href="#创建自己的chart" class="headerlink" title="创建自己的chart"></a>创建自己的chart</h3><p>我们使用<code>kubectl create mychart</code>创建一个名为<code>mychart</code>的chart,看一看chart的文件结构。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">$ helm create mongodb</span><br><span class="line">$ tree mongodb</span><br><span class="line">mongodb</span><br><span class="line"> Chart.yaml <span class="comment">#Chart本身的版本和配置信息</span></span><br><span class="line"> charts <span class="comment">#依赖的chart</span></span><br><span class="line"> templates <span class="comment">#配置模板目录</span></span><br><span class="line"> NOTES.txt <span class="comment">#helm提示信息</span></span><br><span class="line"> deployment.yaml <span class="comment">#kubernetes Deployment object</span></span><br><span class="line"> service.yaml <span class="comment">#kubernetes Serivce</span></span><br><span class="line"> values.yaml <span class="comment">#kubernetes object configuration</span></span><br></pre></td></tr></table></figure><h3 id="模板"><a href="#模板" class="headerlink" title="模板"></a>模板</h3><p><code>Templates</code>目录下是yaml文件的模板,遵循<a href="https://golang.org/pkg/text/template/" target="_blank" rel="noopener">Go template</a>语法。使用过<a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a>的静态网站生成工具的人应该对此很熟悉。我们查看下<code>deployment.yaml</code>文件的内容。</p><h3 id="检查配置和模板是否有效"><a href="#检查配置和模板是否有效" class="headerlink" title="检查配置和模板是否有效"></a>检查配置和模板是否有效</h3><p>当使用kubernetes部署应用的时候实际上讲templates渲染成最终的kubernetes能够识别的yaml格式。</p><p>使用<code>helm install --dry-run --debug <chart_dir></code>命令来验证chart配置。该输出中包含了模板的变量配置与最终渲染的yaml文件。</p><p>我们可以看到Deployment和Service的名字前半截由两个随机的单词组成,最后才是我们在<code>values.yaml</code>中配置的值。</p><h3 id="部署到kubernetes"><a href="#部署到kubernetes" class="headerlink" title="部署到kubernetes"></a>部署到kubernetes</h3><p>在<code>mychart</code>目录下执行下面的命令将nginx部署到kubernetes集群上。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">helm install .</span><br><span class="line">NAME: eating-hound</span><br><span class="line">LAST DEPLOYED: Wed Oct 25 14:58:15 2017</span><br><span class="line">NAMESPACE: default</span><br><span class="line">STATUS: DEPLOYED</span><br><span class="line"></span><br><span class="line">RESOURCES:</span><br><span class="line">==> v1/Service</span><br><span class="line">NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">eating-hound-mychart 10.254.135.68 <none> 80/TCP 0s</span><br><span class="line"></span><br><span class="line">==> extensions/v1beta1/Deployment</span><br><span class="line">NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE</span><br><span class="line">eating-hound-mychart 1 1 1 0 0s</span><br></pre></td></tr></table></figure><p>现在nginx已经部署到kubernetes集群上,本地执行提示中的命令在本地主机上访问到nginx实例。</p><h4 id="查看部署的relaese"><a href="#查看部署的relaese" class="headerlink" title="查看部署的relaese"></a>查看部署的relaese</h4><p>$ helm list<br>NAME REVISION UPDATED STATUS CHART NAMESPACE<br>eating-hound 1 Wed Oct 25 14:58:15 2017 DEPLOYED mychart-0.1.0 default</p><h4 id="删除部署的release"><a href="#删除部署的release" class="headerlink" title="删除部署的release"></a>删除部署的release</h4><p>$ helm delete eating-hound<br>release “eating-hound” deleted</p><h3 id="打包分享"><a href="#打包分享" class="headerlink" title="打包分享"></a>打包分享</h3><p>我们可以修改<code>Chart.yaml</code>中的helm chart配置信息,然后使用下列命令将chart打包成一个压缩文件。</p><p>helm package .</p><p>打包出<code>mychart-0.1.0.tgz</code>文件。</p><h3 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h3><p>我们可以在<code>requirements.yaml</code>中定义应用所依赖的chart,例如定义对<code>mariadb</code>的依赖:</p><p>dependencies:</p><ul><li>name: mariadb<br>version: 0.6.0<br>repository: <a href="https://kubernetes-charts.storage.googleapis.com" target="_blank" rel="noopener">https://kubernetes-charts.storage.googleapis.com</a><br>condition: mariadb.enabled // condition用于是否按照镜像</li></ul><p>使用<code>helm lint .</code>命令可以检查依赖和模板配置是否正确。</p><h3 id="解决本地chart依赖"><a href="#解决本地chart依赖" class="headerlink" title="解决本地chart依赖"></a>解决本地chart依赖</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">helm dependency update</span><br></pre></td></tr></table></figure><h3 id="添加本地chart到远程仓库"><a href="#添加本地chart到远程仓库" class="headerlink" title="添加本地chart到远程仓库"></a>添加本地chart到远程仓库</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">helm repo add .....</span><br></pre></td></tr></table></figure><h3 id="推送本地char到远程仓库"><a href="#推送本地char到远程仓库" class="headerlink" title="推送本地char到远程仓库"></a>推送本地char到远程仓库</h3><p>前提是安装push插件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">helm push charts repo</span><br></pre></td></tr></table></figure><h3 id="部署MEAN测试案例"><a href="#部署MEAN测试案例" class="headerlink" title="部署MEAN测试案例"></a>部署MEAN测试案例</h3><p>MEAN是用来构建网站和web应用的免费开源的JavaScript软件栈,该软件栈包括MongoDB、Express.js、Angular和Node.js。</p><h4 id="下载charts"><a href="#下载charts" class="headerlink" title="下载charts"></a><strong>下载charts</strong></h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ git <span class="built_in">clone</span> https://github.com/bitnami/charts.git</span><br><span class="line">$ <span class="built_in">cd</span> charts/incubator/mean</span><br><span class="line">$ helm dep list</span><br><span class="line">NAME VERSION REPOSITORY STATUS</span><br><span class="line">mongodb 0.4.x https://kubernetes-charts.storage.googleapis.com/ missing</span><br></pre></td></tr></table></figure><p>缺少mongodb的依赖,需要更新一下chart。</p><p><strong>注</strong>:<code>https://kubernetes-charts.storage.googleapis.com/</code>是Google维护的chart库,访问该地址可以看到所有的chart列表。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">$ helm dep update</span><br><span class="line">Hang tight <span class="keyword">while</span> we grab the latest from your chart repositories...</span><br><span class="line">...Unable to get an update from the <span class="string">"local"</span> chart repository (http://127.0.0.1:8879/charts):</span><br><span class="line"> Get http://127.0.0.1:8879/charts/index.yaml: dial tcp 127.0.0.1:8879: getsockopt: connection refused</span><br><span class="line">...Successfully got an update from the <span class="string">"stable"</span> chart repository</span><br><span class="line">Update Complete. ⎈Happy Helming!⎈</span><br><span class="line">Saving 1 charts</span><br><span class="line">Downloading mongodb from repo https://kubernetes-charts.storage.googleapis.com/</span><br></pre></td></tr></table></figure><p>所有的image都在 <code>values.yaml</code> 文件中配置。</p><p>下载缺失的chart。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">$ helm dep build</span><br><span class="line">Hang tight <span class="keyword">while</span> we grab the latest from your chart repositories...</span><br><span class="line">...Unable to get an update from the <span class="string">"local"</span> chart repository (http://127.0.0.1:8879/charts):</span><br><span class="line"> Get http://127.0.0.1:8879/charts/index.yaml: dial tcp 127.0.0.1:8879: getsockopt: connection refused</span><br><span class="line">...Successfully got an update from the <span class="string">"stable"</span> chart repository</span><br><span class="line">Update Complete. ⎈Happy Helming!⎈</span><br><span class="line">Saving 1 charts</span><br><span class="line">Downloading mongodb from repo https://kubernetes-charts.storage.googleapis.com/</span><br></pre></td></tr></table></figure><h4 id="修改mongodb-chart配置"><a href="#修改mongodb-chart配置" class="headerlink" title="修改mongodb chart配置"></a>修改mongodb chart配置</h4><p>将刚才下载的<code>charts/mongodb-0.4.17.tgz</code>给解压后,修改其中的配置:</p><ul><li>将<code>persistence</code>下的<code>enabled</code>设置为false</li><li>将image修改为我们的私有镜像:harbor-001.jimmysong.io/library/bitnami-mongodb:3.4.9-r1</li></ul><p>执行<code>helm install --dry-run --debug .</code>确定模板无误。</p><p>将修改后的mongodb chart打包,在mongodb的目录下执行:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">helm package .</span><br></pre></td></tr></table></figure><p>现在再访问前面启动的helm server <code>http://localhost:8879</code>将可以在页面上看到mongodb-0.4.17这个chart。</p><p>我们对官方chart配置做了如下修改后推送到了自己的chart仓库:</p><p><strong>注</strong>:因为我们没有使用PVC所以将所有的关于持久化存储的配置都设置为false了。</p><h4 id="部署MEAN"><a href="#部署MEAN" class="headerlink" title="部署MEAN"></a><strong>部署MEAN</strong></h4><p>在<code>mean</code>目录下执行:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">helm install .</span><br><span class="line">NAME: orbiting-platypus</span><br><span class="line">LAST DEPLOYED: Wed Oct 25 16:21:48 2017</span><br><span class="line">NAMESPACE: default</span><br><span class="line">STATUS: DEPLOYED</span><br><span class="line"></span><br><span class="line">RESOURCES:</span><br><span class="line">==> v1/Secret</span><br><span class="line">NAME TYPE DATA AGE</span><br><span class="line">orbiting-platypus-mongodb Opaque 2 2s</span><br><span class="line"></span><br><span class="line">==> v1/ConfigMap</span><br><span class="line">NAME DATA AGE</span><br><span class="line">orbiting-platypus-mean 1 2s</span><br><span class="line"></span><br><span class="line">==> v1/Service</span><br><span class="line">NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">orbiting-platypus-mongodb 10.254.144.208 <none> 27017/TCP 2s</span><br><span class="line">orbiting-platypus-mean 10.254.165.23 <none> 80/TCP 2s</span><br><span class="line"></span><br><span class="line">==> extensions/v1beta1/Deployment</span><br><span class="line">NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE</span><br><span class="line">orbiting-platypus-mean 1 1 1 0 2s</span><br><span class="line">orbiting-platypus-mongodb 1 1 1 0 2s</span><br></pre></td></tr></table></figure><p>这样MEAN软件栈就部署到你的kuberentes集群里面了(默认是在default namespace下)。</p><p>####<strong>验证检查</strong></p><p>为了验证MEAN是否安装成功过,可以使用<code>kubectl get pods</code>查看pod是否启动完成,会先启动mongodb的pod,然后启动MEAN中的4步init。</p><h4 id="访问Web-UI"><a href="#访问Web-UI" class="headerlink" title="访问Web UI"></a><strong>访问Web UI</strong></h4><p>在Ingress中增加如下配置:</p><ul><li>host: mean.jimmysong.io<br>http:<br> paths:<ul><li>backend:<br> serviceName: orbiting-platypus-mean<br> servicePort: 80<br>path: /</li></ul></li></ul><p>然后在页面中更新ingress:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kubectl repalce -f ingress.yaml</span><br></pre></td></tr></table></figure><p>然后在本地的<code>/etc/hosts</code>文件中增加一条配置:</p><p><strong>注</strong>:172.20.0.119即边缘节点的VIP。</p><p>因为该页面需要加载google的angularjs、还有两个css在国内无法访问,可以使用curl测试:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl mean.jimmysong.io</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<blockquote>
<p>Helm is the best way to find, share, and use software built for Kubernetes.</p>
</blockquote>
<p>Helm会通过读取Kubernetes配置文件(通常是$HOME/.kube/config)来找到安装Tiller的位置。这与kubectl使用的文件相同。要确定将把Tiller安装到哪个集群,可以运行kubectl配置current-context或kubectl cluster-info。</p>
<h3 id="安装Helm和安装Tiller"><a href="#安装Helm和安装Tiller" class="headerlink" title="安装Helm和安装Tiller"></a>安装Helm和安装Tiller</h3><h4 id="初始化Helm和安装Tiller"><a href="#初始化Helm和安装Tiller" class="headerlink" title="初始化Helm和安装Tiller"></a>初始化Helm和安装Tiller</h4><p>准备好Helm后,您可以初始化本地CLI,也可以一步将Tiller安装到Kubernetes集群中:。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ helm init</span><br></pre></td></tr></table></figure>
<p>这将把Tiller安装到您在kubectl配置当前上下文中看到的Kubernetes集群中。</p>
</summary>
<category term="k8s" scheme="http://www.chenfanlinux.org/categories/k8s/"/>
<category term="Helm" scheme="http://www.chenfanlinux.org/tags/Helm/"/>
</entry>
<entry>
<title>如何更好的管理—-编译-发布代码</title>
<link href="http://www.chenfanlinux.org/2019/03/15/%E5%A6%82%E4%BD%95%E6%9B%B4%E5%A5%BD%E7%9A%84%E7%AE%A1%E7%90%86%E2%80%94-%E7%BC%96%E8%AF%91-%E5%8F%91%E5%B8%83%E4%BB%A3%E7%A0%81/"/>
<id>http://www.chenfanlinux.org/2019/03/15/如何更好的管理—-编译-发布代码/</id>
<published>2019-03-15T15:34:53.000Z</published>
<updated>2019-03-15T15:38:12.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>相信每个公司都有自己代码管理策略,如何更好的在团队开发中使用版本控制系统,商定一个统一的工作流程至关重要。将代码根据管理策略进行管理,那么如何更好的编译你的代码,发布你的代码自动发布到测试环境-预发布环境-生产环境,这又是一个亟待解决的重要问题。下面我给大家介绍一下,我们公司的代码管理-编译-发布等系列流程,希望跟大家一起交流,共同进步。</p></blockquote><h2 id="如何更好的管理代码"><a href="#如何更好的管理代码" class="headerlink" title="如何更好的管理代码?"></a>如何更好的管理代码?</h2><p>当在团队开发中使用版本控制系统时,商定一个统一的工作流程是至关重要的。Git 的确可以在各个方面做很多事情,然而,如果在你的团队中还没有能形成一个特定有效的工作流程,那么混乱就将是不可避免的。下面我给大家介绍一下我们公司使用的非常流行的工作流程 git-flow。</p><h3 id="在项目中设置git-flow"><a href="#在项目中设置git-flow" class="headerlink" title="在项目中设置git-flow"></a>在项目中设置git-flow</h3><p>当你想把你的项目 “切换” 到 git-flow 上后,Git 还是可以像往常一样工作的。这完全是取决于你在仓库上使用特殊的 git-flow 命令或是普通的 Git 命令。换句话说,git-flow 它不会以任何一种戏剧性的方式来改变你的仓库。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ git flow init</span><br><span class="line">Initialized empty Git repository in /Users/tobi/acme-website/.git/</span><br><span class="line">Branch name for production releases: [master]</span><br><span class="line">Branch name for "next release" development: [develop]</span><br><span class="line"></span><br><span class="line">How to name your supporting branch prefixes?</span><br><span class="line">Feature branches? [feature/]</span><br><span class="line">Release branches? [release/]</span><br><span class="line">Hotfix branches? [hotfix/]</span><br></pre></td></tr></table></figure><p>当在项目的根目录执行 “git flow init” 命令时(它是否已经包括了一个 Git 仓库并不重要),一个交互式安装助手将引导您完成这个初始化操作。听起来是不是有点炫,但实际上它只是在你的分支上配置了一些命名规则。</p><a id="more"></a><h3 id="分支的模式"><a href="#分支的模式" class="headerlink" title="分支的模式"></a>分支的模式</h3><p>git-flow 模式会预设两个主分支在仓库中:</p><ul><li><strong>master</strong> 只能用来包括产品代码。你不能直接工作在这个 master 分支上,而是在其他指定的,独立的特性分支中(这方面我们会马上谈到)。不直接提交改动到 <em>master</em> 分支上也是很多工作流程的一个共同的规则。</li><li><strong>develop</strong> 是你进行任何新的开发的基础分支。当你开始一个新的功能分支时,它将是<em>开发</em>的基础。另外,该分支也汇集所有已经完成的功能,并等待被整合到 <em>master</em> 分支中。</li></ul><p><img src="https://s2.ax1x.com/2019/03/15/AEYMUs.png" alt=""></p><p>这两个分支被称作为 <a href="https://www.git-tower.com/learn/git/ebook/cn/command-line/branching-merging/branching-workflows" target="_blank" rel="noopener">长期分支</a>。它们会存活在项目的整个生命周期中。而其他的分支,例如针对功能的分支,针对发行的分支,仅仅只是临时存在的。它们是根据需要来创建的,当它们完成了自己的任务之后就会被删除掉。</p><p><img src="https://s2.ax1x.com/2019/03/15/AEY82V.png" alt="fhfh"></p><h3 id="功能开发"><a href="#功能开发" class="headerlink" title="功能开发"></a>功能开发</h3><p>对于一个开发人员来说,最平常的工作可能就是功能的开发。这就是为什么 git-flow 定义了很多对于功能开发的工作流程,从而来帮助你有组织地完成它。</p><h4 id="开始新功能"><a href="#开始新功能" class="headerlink" title="开始新功能"></a>开始新功能</h4><p>让我们开始开发一个新功能 “rss-feed”, 我们公司按照迭代名称来命令新功能。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ git flow feature start rss-feed</span><br><span class="line">Switched to a new branch <span class="string">'feature/rss-feed'</span></span><br><span class="line"></span><br><span class="line">Summary of actions:</span><br><span class="line">- A new branch <span class="string">'feature/rss-feed'</span> was created, based on <span class="string">'develop'</span></span><br><span class="line">- You are now on branch <span class="string">'feature/rss-feed'</span></span><br></pre></td></tr></table></figure><p>正如上面这个新功能一样,git-flow 会创建一个名为 “feature/rss-feed” 的分支(这个 “feature/” 前缀 是一个可配置的选项设置)。你已经知道了,在你做新功能开发时使用一个独立的分支是版本控制中最重要的规则之一。<br>git-flow 也会直接签出这个新的分支,这样你就可以直接进行工作了。</p><h4 id="完成一个功能"><a href="#完成一个功能" class="headerlink" title="完成一个功能"></a>完成一个功能</h4><p>经过一段时间艰苦地工作和一系列的聪明提交,我们的新功能终于完成了:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">$ git flow feature finish rss-feed</span><br><span class="line">Switched to branch <span class="string">'develop'</span></span><br><span class="line">Updating 6bcf266..41748ad</span><br><span class="line">Fast-forward</span><br><span class="line"> feed.xml | 0</span><br><span class="line"> 1 file changed, 0 insertions(+), 0 deletions(-)</span><br><span class="line"> create mode 100644 feed.xml</span><br><span class="line">Deleted branch feature/rss-feed (was 41748ad).</span><br></pre></td></tr></table></figure><p>最重要的是,这个 “feature finish” 命令会把我们的工作整合到主 “develop” 分支中去。在这里它需要等待:</p><ol><li>一个在更广泛的 “开发” 背景下的全面测试。</li><li>稍后和所有积攒在 “develop” 分支中的其它功能一起进行发布。</li></ol><p>之后,git-flow 也会进行清理操作。它会删除这个当下已经完成的功能分支,并且换到 “develop” 分支。</p><h3 id="管理release"><a href="#管理release" class="headerlink" title="管理release"></a>管理release</h3><p>Release 管理是版本控制处理中的另外一个非常重要的话题。让我们来看看如何利用 git-flow 创建和发布 release。</p><h4 id="创建-release"><a href="#创建-release" class="headerlink" title="创建 release"></a>创建 release</h4><p>当你认为现在在 “develop” 分支的代码已经是一个成熟的 release 版本时,这意味着:第一,它包括所有新的功能和必要的修复;第二,它已经被彻底的测试过了。如果上述两点都满足,那就是时候开始生成一个新的 release 了:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git flow release start 1.1.5</span><br><span class="line">Switched to a new branch <span class="string">'release/1.1.5'</span></span><br></pre></td></tr></table></figure><p>请注意,release 分支是使用版本号命名的。这是一个明智的选择,这个命名方案还有一个很好的附带功能,那就是当我们完成了release 后,git-flow 会适当地<em>自动</em>去标记那些 release 提交。有了这个版本后,方便我们后面针对这个版本的代码进行编译和发布工作。</p><h4 id="完成-release"><a href="#完成-release" class="headerlink" title="完成 release"></a>完成 release</h4><p>现在是时候按下那个危险的红色按钮来完成我们的release了:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git flow release finish 1.1.5</span><br></pre></td></tr></table></figure><p>这个命令会完成如下一系列的操作:</p><ol><li>首先,git-flow 会拉取远程仓库,以确保目前是最新的版本。</li><li>然后,release 的内容会被合并到 “master” 和 “develop” 两个分支中去,这样不仅产品代码为最新的版本,而且新的功能分支也将基于最新代码。</li><li>为便于识别和做历史参考,release 提交会被标记上这个 release 的名字(在我们的例子里是 “1.1.5”)。</li><li>清理操作,版本分支会被删除,并且回到 “develop”。</li></ol><h3 id="hotfix"><a href="#hotfix" class="headerlink" title="hotfix"></a>hotfix</h3><p>很多时候,仅仅在几个小时或几天之后,当对 release 版本作做全面测试时,可能就会发现一些小错误。<br>在这种情况下,git-flow 提供一个特定的 “hotfix” 工作流程(因为在这里不管使用 “功能” 分支流程,还是 “release” 分支流程都是不恰当的), 我们公司按照当天时间来命令hotfix。</p><h4 id="创建-Hotfixes"><a href="#创建-Hotfixes" class="headerlink" title="创建 Hotfixes"></a>创建 Hotfixes</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git flow hotfix start missing-link</span><br></pre></td></tr></table></figure><p>这个命令会创建一个名为 “hotfix/missing-link” 的分支。因为这是对产品代码进行修复,所以这个 hotfix 分支是基于 “master” 分支。这也是和 release 分支最明显的区别,release 分支都是基于 “develop” 分支的。因为你不应该在一个还不完全稳定的开发分支上对产品代码进行地修复。就像 release 一样,修复这个错误当然也会直接影响到项目的版本号!</p><h4 id="完成-Hotfixes"><a href="#完成-Hotfixes" class="headerlink" title="完成 Hotfixes"></a>完成 Hotfixes</h4><p>在把我们的修复提交到 hotfix 分支之后,就该去完成它了:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ git flow hotfix finish missing-link</span><br><span class="line"><span class="comment"># 我们会重新生成一个tag号</span></span><br><span class="line">$ git flow hotfix start v3.15.1</span><br><span class="line">$ git flow hotfix finish v3.15.1</span><br></pre></td></tr></table></figure><p>这个过程非常类似于发布一个 release 版本:</p><ul><li>完成的改动会被合并到 “master” 中,同样也会合并到 “develop” 分支中,这样就可以确保这个错误不会再次出现在下一个 release 中。</li><li>这个 hotfix 程序将被标记起来以便于参考。</li><li>这个 hotfix 分支将被删除,然后切换到 “develop” 分支上去。</li><li>我们公司会对这个hotfix再打一个版本号,基于这个版本号,生成一个tag,用于hotfix小版本发布。</li></ul><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ol><li>当feature功能完成后,开发合并代码到develop分支。</li><li>develop代码经过会部署到develop环境,经过测试充分测试。</li><li>测试人员测试develop代码无问题后,会基于这个分支代码打一个release tag号,例如3.15.0。</li><li>基于release tag号,用于正式环境发布服务。</li><li>如果发现线上环境出现问题,会从master分支签出一个hotfix分支,然后基于完成的hotfix,再打一个hotfix tag号,例如3.15.1。</li><li>正式发版基于tag号,测试发版基于分支名。</li></ol><h2 id="如何更好的编译不同分支的代码?"><a href="#如何更好的编译不同分支的代码?" class="headerlink" title="如何更好的编译不同分支的代码?"></a>如何更好的编译不同分支的代码?</h2><p>开发的代码有不同的分支还有不同的tag号,基于这种代码管理策略,我们选择了jenkins中的多分支管理策略。</p><h3 id="Git源部分的配置"><a href="#Git源部分的配置" class="headerlink" title="Git源部分的配置"></a>Git源部分的配置</h3><h4 id="基于release-tag的配置"><a href="#基于release-tag的配置" class="headerlink" title="基于release tag的配置"></a>基于release tag的配置</h4><p>v[0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}$</p><p><img src="https://s2.ax1x.com/2019/03/15/AENf3t.png" alt="release tag"></p><p>基于上面的分支源,我们可以发现如下Tags</p><p><img src="https://s2.ax1x.com/2019/03/15/AENTHg.png" alt="git tag"></p><h4 id="基于branch的配置"><a href="#基于branch的配置" class="headerlink" title="基于branch的配置"></a>基于branch的配置</h4><p>([A-Z]\d{3}|develop|refactor|hotfix/.<em>|feature/.</em>|release/v[\d.]+)</p><p><img src="https://s2.ax1x.com/2019/03/15/AEUSDU.png" alt="branch"></p><p>基于上面的分支源,我们可以发现如下branches</p><p><img src="https://s2.ax1x.com/2019/03/15/AEUtr8.png" alt=""></p><h3 id="Build配置"><a href="#Build配置" class="headerlink" title="Build配置"></a>Build配置</h3><p>Build部分,我们基于Jenkins语法,完成代码的编译以及代码测试和发布工作。</p><h4 id="jenkinsflie结构如下"><a href="#jenkinsflie结构如下" class="headerlink" title="jenkinsflie结构如下"></a>jenkinsflie结构如下</h4><p>匹配不同的分支,根据条件判断,执行不同的stage。每个stage包括打包,构建,数据迁移,部署,测试,通知发送等步骤。这些步骤如果太复杂可以定义在make.sh脚本中,用于jenkinsfile来调用。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br></pre></td><td class="code"><pre><span class="line">stages{</span><br><span class="line"> stage(<span class="string">'feature'</span>){</span><br><span class="line"> when{</span><br><span class="line"> expression { BRANCH_NAME ==~ /^feature\/.*/ }</span><br><span class="line"> }</span><br><span class="line"> environment {</span><br><span class="line"> def tag = BRANCH_NAME.split(<span class="string">'/'</span>).toList().get(1)</span><br><span class="line"> def namespace = tag.toLowerCase()</span><br><span class="line"> BITBUCKET_COMMON_CREDS = credentials(<span class="string">'f35b4a1e-7673-4bb8-8c00-7acbc37032a9'</span>)</span><br><span class="line"> def TEST_USERNAME = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_USR}</span>"</span></span><br><span class="line"> def TEST_PASSWORD = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_PSW}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> stages {</span><br><span class="line"> stage(<span class="string">'Package'</span>){</span><br><span class="line"> steps{</span><br><span class="line"> sh <span class="string">"make.sh package <span class="variable">${namespace}</span> <span class="variable">${tag}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'Build'</span>){</span><br><span class="line"> steps{</span><br><span class="line"> sh <span class="string">"make.sh bulid <span class="variable">${tag}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'migrate data'</span>){</span><br><span class="line"> steps{</span><br><span class="line"> sh <span class="string">"migrate"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> stage(<span class="string">'deploy'</span>){</span><br><span class="line"> steps{</span><br><span class="line"> sh <span class="string">"make.sh deploy <span class="variable">${namespace}</span> <span class="variable">${tag}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> stage(<span class="string">'test'</span>){</span><br><span class="line"> steps{</span><br><span class="line"> sh <span class="string">"make.sh test <span class="variable">${namespace}</span> <span class="variable">${tag}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> stage(<span class="string">'ding'</span>){</span><br><span class="line"> steps{</span><br><span class="line"> sh <span class="string">"make.sh test <span class="variable">${namespace}</span> <span class="variable">${tag}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> stage(<span class="string">'hotfix'</span>) {</span><br><span class="line"> when{</span><br><span class="line"> expression { BRANCH_NAME ==~ /^hotfix\/.*/ }</span><br><span class="line"> }</span><br><span class="line"> environment {</span><br><span class="line"> def tag = BRANCH_NAME.split(<span class="string">'/'</span>)toList().get(1).replaceAll(<span class="string">"\\."</span>,<span class="string">'-'</span>)</span><br><span class="line"> def namespace = tag.toLowerCase()</span><br><span class="line"> BITBUCKET_COMMON_CREDS = credentials(<span class="string">'f35b4a1e-7673-4bb8-8c00-7acbc37032a9'</span>)</span><br><span class="line"> def TEST_USERNAME = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_USR}</span>"</span></span><br><span class="line"> def TEST_PASSWORD = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_PSW}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> stages{</span><br><span class="line"> stage(<span class="string">'Package'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'Build'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'migrate data'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'deploy'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'test'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'ding'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> stage(<span class="string">'develop'</span>) {</span><br><span class="line"> when{</span><br><span class="line"> anyOf{</span><br><span class="line"> branch <span class="string">'develop'</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> environment {</span><br><span class="line"> def tag = BRANCH_NAME.split(<span class="string">'/'</span>)toList().get(1).replaceAll(<span class="string">"\\."</span>,<span class="string">'-'</span>)</span><br><span class="line"> def namespace = tag.toLowerCase()</span><br><span class="line"> BITBUCKET_COMMON_CREDS = credentials(<span class="string">'f35b4a1e-7673-4bb8-8c00-7acbc37032a9'</span>)</span><br><span class="line"> def TEST_USERNAME = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_USR}</span>"</span></span><br><span class="line"> def TEST_PASSWORD = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_PSW}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> stages{</span><br><span class="line"> stage(<span class="string">'Package'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'Build'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'migrate data'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'deploy'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'test'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'ding'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> stage(<span class="string">'release'</span>) {</span><br><span class="line"> when { tag pattern: <span class="string">"v[0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}"</span>, comparator: <span class="string">"REGEXP"</span> }</span><br><span class="line"> environment {</span><br><span class="line"> def tag = BRANCH_NAME.toLowerCase()</span><br><span class="line"> // def namespace = <span class="string">"product"</span></span><br><span class="line"> def namespace = input message: <span class="string">'Where do you want to deploy to which namespace?'</span>, ok: <span class="string">'commit'</span>, parameters: [choice(choices: [<span class="string">'product'</span>, <span class="string">'blue'</span>, <span class="string">'green'</span>], description: <span class="string">'product,blue,green'</span>, name: <span class="string">'namespace'</span>)]</span><br><span class="line"> BITBUCKET_COMMON_CREDS = credentials(<span class="string">'f35b4a1e-7673-4bb8-8c00-7acbc37032a9'</span>)</span><br><span class="line"> def PRODUCTION_USERNAME = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_USR}</span>"</span></span><br><span class="line"> def PRODUCTION_PASSWORD = <span class="string">"<span class="variable">${BITBUCKET_COMMON_CREDS_PSW}</span>"</span></span><br><span class="line"> }</span><br><span class="line"> stages{</span><br><span class="line"> stage(<span class="string">'Package'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'Build'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'migrate data'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'deploy'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'test'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> stage(<span class="string">'ding'</span>){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="make-sh"><a href="#make-sh" class="headerlink" title="make.sh"></a>make.sh</h4><p>这个用于定义函数被jenkins调用。</p><h4 id="jenkins流程图"><a href="#jenkins流程图" class="headerlink" title="jenkins流程图"></a>jenkins流程图</h4><p>stage有feature,hotfix,develop,release等,其中只是显示一个release,用于根据tag发版。</p><p><img src="https://s2.ax1x.com/2019/03/15/AEajmT.png" alt=""></p><h2 id="如何更好的发布代码"><a href="#如何更好的发布代码" class="headerlink" title="如何更好的发布代码"></a>如何更好的发布代码</h2><h3 id="Docker镜像的构建"><a href="#Docker镜像的构建" class="headerlink" title="Docker镜像的构建"></a>Docker镜像的构建</h3><p>目前我们把开发代码中会嵌入我们的Dockerfile和make.sh脚本,将运维脚本嵌入开发代码,为了在jenkins的workspace中mvn代码,获取jar包,并且通过Dockerfile,构建镜像,推送镜像仓库。</p><h3 id="k8s容器编排"><a href="#k8s容器编排" class="headerlink" title="k8s容器编排"></a>k8s容器编排</h3><p>目前我们使用阿里云的容器服务,阿里云的容器服务只收取ecs费用,相对于自建来说,成本更低。所以我们选择阿里云的容器服务,降低手工部署的繁琐性和维护成本。k8s的重点不在于安装部署,而在于容器的编排。目前我们只有一套集群,正式服务和测试服务都部署到一个集群当中,通过节点的亲和性。将测试环境部署到打有测试标记的节点上,让证书服务部署到打有正式服务器标签的节点上。</p><h3 id="Helm发布测试和正式环境应用"><a href="#Helm发布测试和正式环境应用" class="headerlink" title="Helm发布测试和正式环境应用"></a>Helm发布测试和正式环境应用</h3><p>针对测试和生成环境,我们生成了两个helm包。分别用于正式环境和测试环境服务的部署工作。在jenkins容器的内部,我们安装了helm客户端,用于发布应用程序。helm可以—set传入tag号和namespace,将测试服务部署到其namesapce当中。正式环境我们有blue和green环境,通过istio来进行流量切换。发布代码到bule或者green,通过jenkins传入变量来控制。</p><p>目前我们将不同的微服务应用打包成独立的charts, 全局控制chart是否安装,使得部署更加灵活和稳定。</p><p><img src="https://s2.ax1x.com/2019/03/15/AEyKVx.png" alt="helm"></p><p>blue和green为预发布和生成环境的切换,其他都是根据不同特性分支命名的部署release, 分别位于不同的名称空间中。</p><p><img src="https://s2.ax1x.com/2019/03/15/AEsIKA.png" alt=""></p><h3 id="Istio用于蓝绿部署"><a href="#Istio用于蓝绿部署" class="headerlink" title="Istio用于蓝绿部署"></a>Istio用于蓝绿部署</h3><p>istio后面我会总结相应的文档进行说明。目前我们用istio 中gateway和virtualservice将正式流量指向blue或者green环境,来控制我们的代码版本。正式上线的时候,我们会先通过jenkins将代码部署到预发布环境,测试人员对预发布环境进行测试,当测试通过时,我们会切换流量到预发布环境,此时预发布环境变成正式环境。istio的功能远远不止如此</p><p><img src="https://s2.ax1x.com/2019/03/15/AEyPaV.png" alt="istio"></p><p>virtualservie 7层用于流量的转发,可以通过header匹配不同’blue’或者’green’进入到不同的环境。生产环境通过weight流量权重控制,将流量导入到blue或者green环境当中。</p>]]></content>
<summary type="html">
<blockquote>
<p>相信每个公司都有自己代码管理策略,如何更好的在团队开发中使用版本控制系统,商定一个统一的工作流程至关重要。将代码根据管理策略进行管理,那么如何更好的编译你的代码,发布你的代码自动发布到测试环境-预发布环境-生产环境,这又是一个亟待解决的重要问题。下面我给大家介绍一下,我们公司的代码管理-编译-发布等系列流程,希望跟大家一起交流,共同进步。</p>
</blockquote>
<h2 id="如何更好的管理代码"><a href="#如何更好的管理代码" class="headerlink" title="如何更好的管理代码?"></a>如何更好的管理代码?</h2><p>当在团队开发中使用版本控制系统时,商定一个统一的工作流程是至关重要的。Git 的确可以在各个方面做很多事情,然而,如果在你的团队中还没有能形成一个特定有效的工作流程,那么混乱就将是不可避免的。下面我给大家介绍一下我们公司使用的非常流行的工作流程 git-flow。</p>
<h3 id="在项目中设置git-flow"><a href="#在项目中设置git-flow" class="headerlink" title="在项目中设置git-flow"></a>在项目中设置git-flow</h3><p>当你想把你的项目 “切换” 到 git-flow 上后,Git 还是可以像往常一样工作的。这完全是取决于你在仓库上使用特殊的 git-flow 命令或是普通的 Git 命令。换句话说,git-flow 它不会以任何一种戏剧性的方式来改变你的仓库。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ git flow init</span><br><span class="line">Initialized empty Git repository in /Users/tobi/acme-website/.git/</span><br><span class="line">Branch name for production releases: [master]</span><br><span class="line">Branch name for &quot;next release&quot; development: [develop]</span><br><span class="line"></span><br><span class="line">How to name your supporting branch prefixes?</span><br><span class="line">Feature branches? [feature/]</span><br><span class="line">Release branches? [release/]</span><br><span class="line">Hotfix branches? [hotfix/]</span><br></pre></td></tr></table></figure>
<p>当在项目的根目录执行 “git flow init” 命令时(它是否已经包括了一个 Git 仓库并不重要),一个交互式安装助手将引导您完成这个初始化操作。听起来是不是有点炫,但实际上它只是在你的分支上配置了一些命名规则。</p>
</summary>
<category term="持续集成-部署" scheme="http://www.chenfanlinux.org/categories/%E6%8C%81%E7%BB%AD%E9%9B%86%E6%88%90-%E9%83%A8%E7%BD%B2/"/>
<category term="k8s" scheme="http://www.chenfanlinux.org/tags/k8s/"/>
<category term="Git" scheme="http://www.chenfanlinux.org/tags/Git/"/>
</entry>
<entry>
<title>k8s中使用cert-manager玩转证书</title>
<link href="http://www.chenfanlinux.org/2019/03/15/k8s%E4%B8%AD%E4%BD%BF%E7%94%A8cert-manager%E7%8E%A9%E8%BD%AC%E8%AF%81%E4%B9%A6/"/>
<id>http://www.chenfanlinux.org/2019/03/15/k8s中使用cert-manager玩转证书/</id>
<published>2019-03-15T15:15:08.000Z</published>
<updated>2019-03-15T15:31:47.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>如果k8s集群上部署应用较多,要为每个应用的不同域名生产https证书,操作太麻烦了。上述这些手动操作没有跟k8s的deployment描述文件放在一起记录起来,很容易遗忘。证书过期后,又得手动执行命令重新生成证书。因此,这都是我们使用cert-manager的理由。</p></blockquote><h3 id="cert-manager的架构"><a href="#cert-manager的架构" class="headerlink" title="cert-manager的架构"></a>cert-manager的架构</h3><p><img src="https://s2.ax1x.com/2019/03/15/AE1yJf.png" alt="cert-manager"></p><p>上面是官方给出的架构图,可以看到cert-manager在k8s中定义了两个自定义类型资源:<code>Issuer</code>和<code>Certificate</code>。</p><p>其中<code>Issuer</code>代表的是证书颁发者,可以定义各种提供者的证书颁发者,当前支持基于<code>Letsencrypt</code>、<code>vault</code>和<code>CA</code>的证书颁发者,还可以定义不同环境下的证书颁发者。</p><p>而<code>Certificate</code>代表的是生成证书的请求,一般其中存入生成证书的元信息,如域名等等。</p><p>一旦在k8s中定义了上述两类资源,部署的<code>cert-manager</code>则会根据<code>Issuer</code>和<code>Certificate</code>生成TLS证书,并将证书保存进k8s的<code>Secret</code>资源中,然后在<code>Ingress</code>资源中就可以引用到这些生成的<code>Secret</code>资源。对于已经生成的证书,还是定期检查证书的有效期,如即将超过有效期,还会自动续期。</p><h3 id="部署cert-manager"><a href="#部署cert-manager" class="headerlink" title="部署cert-manager"></a>部署cert-manager</h3><p>部署cert-manager还是比较简单的,直接用helm部署就可以了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">helm install \</span><br><span class="line"> --name cert-manager \</span><br><span class="line"> --namespace kube-system \</span><br><span class="line"> stable/cert-manager</span><br></pre></td></tr></table></figure><a id="more"></a><h3 id="创建ClusterIssuer"><a href="#创建ClusterIssuer" class="headerlink" title="创建ClusterIssuer"></a>创建ClusterIssuer</h3><p>clusterissuer.yaml</p><p>kubectl apply -f nginx.yaml</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">apiVersion: certmanager.k8s.io/v1alpha1</span><br><span class="line">kind: ClusterIssuer</span><br><span class="line">metadata:</span><br><span class="line"> name: letsencrypt-prod</span><br><span class="line">spec:</span><br><span class="line"> acme:</span><br><span class="line"> server: https://acme-v02.api.letsencrypt.org/directory</span><br><span class="line"> email: chenfan@aixiangdao.com</span><br><span class="line"> privateKeySecretRef:</span><br><span class="line"> name: letsencrypt-prod</span><br><span class="line"> http01: {}</span><br></pre></td></tr></table></figure><p>kubectl apply -f clusterissuer.yaml</p><h4 id="nginx应用cert-manager"><a href="#nginx应用cert-manager" class="headerlink" title="nginx应用cert-manager"></a>nginx应用cert-manager</h4><p><strong>nginx.yaml</strong></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr"> name:</span> <span class="string">myapp-deploy</span></span><br><span class="line"><span class="attr"> namespace:</span> <span class="string">chenfanlinux</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr"> replicas:</span> <span class="number">2</span></span><br><span class="line"><span class="attr"> selector:</span></span><br><span class="line"><span class="attr"> matchLabels:</span></span><br><span class="line"><span class="attr"> app:</span> <span class="string">myapp</span></span><br><span class="line"><span class="attr"> release:</span> <span class="string">canary</span></span><br><span class="line"><span class="attr"> template:</span></span><br><span class="line"><span class="attr"> metadata:</span></span><br><span class="line"><span class="attr"> labels:</span></span><br><span class="line"><span class="attr"> app:</span> <span class="string">myapp</span></span><br><span class="line"><span class="attr"> release:</span> <span class="string">canary</span></span><br><span class="line"><span class="attr"> spec:</span></span><br><span class="line"><span class="attr"> containers:</span></span><br><span class="line"><span class="attr"> - name:</span> <span class="string">myapp</span></span><br><span class="line"><span class="attr"> image:</span> <span class="string">ikubernetes/myapp:v1</span></span><br><span class="line"><span class="attr"> ports:</span></span><br><span class="line"><span class="attr"> - name:</span> <span class="string">http</span></span><br><span class="line"><span class="attr"> containerPort:</span> <span class="number">80</span></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Service</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr"> name:</span> <span class="string">myapp</span></span><br><span class="line"><span class="attr"> namespace:</span> <span class="string">chenfanlinux</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr"> selector:</span></span><br><span class="line"><span class="attr"> app:</span> <span class="string">myapp</span></span><br><span class="line"><span class="attr"> release:</span> <span class="string">canary</span></span><br><span class="line"><span class="attr"> ports:</span></span><br><span class="line"><span class="attr"> - name:</span> <span class="string">http</span></span><br><span class="line"><span class="attr"> port:</span> <span class="number">80</span> <span class="comment"># service port</span></span><br><span class="line"><span class="attr"> targetPort:</span> <span class="number">80</span> <span class="comment"># pod port</span></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">extensions/v1beta1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Ingress</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"><span class="attr"> name:</span> <span class="string">ingress-myapp</span></span><br><span class="line"><span class="attr"> namespace:</span> <span class="string">chenfanlinux</span></span><br><span class="line"><span class="attr"> annotations:</span></span><br><span class="line"> <span class="string">kubernetes.io/ingress.class:</span> <span class="string">nginx</span></span><br><span class="line"> <span class="string">certmanager.k8s.io/cluster-issuer:</span> <span class="string">letsencrypt-prod</span></span><br><span class="line"> <span class="string">kubernetes.io/tls-acme:</span> <span class="string">"true"</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"><span class="attr"> rules:</span></span><br><span class="line"><span class="attr"> - host:</span> <span class="string">myapp.aixiangdao.tech</span></span><br><span class="line"><span class="attr"> http:</span></span><br><span class="line"><span class="attr"> paths:</span></span><br><span class="line"><span class="attr"> - path:</span> <span class="string">/</span></span><br><span class="line"><span class="attr"> backend:</span></span><br><span class="line"><span class="attr"> serviceName:</span> <span class="string">myapp</span></span><br><span class="line"><span class="attr"> servicePort:</span> <span class="number">80</span></span><br><span class="line"><span class="attr"> tls:</span></span><br><span class="line"><span class="attr"> - hosts:</span></span><br><span class="line"><span class="bullet"> -</span> <span class="string">myapp.aixiangdao.tech</span></span><br><span class="line"><span class="attr"> secretName:</span> <span class="string">myapp</span></span><br></pre></td></tr></table></figure><p><strong>说明:</strong></p><ol><li><p>只需要在ingress增加如下注解即可</p><p>annotations:<br>kubernetes.io/ingress.class: nginx<br>certmanager.k8s.io/cluster-issuer: letsencrypt-prod<br>kubernetes.io/tls-acme: “true”</p></li><li><p>可以查看证书的签发情况</p><p>kubectl describe certificates -n chenfanlinux</p><p>Normal CreateOrder 7m cert-manager Created new ACME order, attempting validation…<br>Normal DomainVerified 1m cert-manager Domain “myapp.aixiangdao.tech” verified with “http-01” validation<br>Normal IssueCert 1m cert-manager Issuing certificate…<br>Normal CertObtained 1m cert-manager Obtained certificate from ACME server<br>Normal CertIssued 1m cert-manager Certificate issued successfully</p></li></ol><p><strong>浏览器访问:</strong></p><p><img src="https://s2.ax1x.com/2019/03/15/AEGFZd.png" alt="浏览器"></p>]]></content>
<summary type="html">
<blockquote>
<p>如果k8s集群上部署应用较多,要为每个应用的不同域名生产https证书,操作太麻烦了。上述这些手动操作没有跟k8s的deployment描述文件放在一起记录起来,很容易遗忘。证书过期后,又得手动执行命令重新生成证书。因此,这都是我们使用cert-manager的理由。</p>
</blockquote>
<h3 id="cert-manager的架构"><a href="#cert-manager的架构" class="headerlink" title="cert-manager的架构"></a>cert-manager的架构</h3><p><img src="https://s2.ax1x.com/2019/03/15/AE1yJf.png" alt="cert-manager"></p>
<p>上面是官方给出的架构图,可以看到cert-manager在k8s中定义了两个自定义类型资源:<code>Issuer</code>和<code>Certificate</code>。</p>
<p>其中<code>Issuer</code>代表的是证书颁发者,可以定义各种提供者的证书颁发者,当前支持基于<code>Letsencrypt</code>、<code>vault</code>和<code>CA</code>的证书颁发者,还可以定义不同环境下的证书颁发者。</p>
<p>而<code>Certificate</code>代表的是生成证书的请求,一般其中存入生成证书的元信息,如域名等等。</p>
<p>一旦在k8s中定义了上述两类资源,部署的<code>cert-manager</code>则会根据<code>Issuer</code>和<code>Certificate</code>生成TLS证书,并将证书保存进k8s的<code>Secret</code>资源中,然后在<code>Ingress</code>资源中就可以引用到这些生成的<code>Secret</code>资源。对于已经生成的证书,还是定期检查证书的有效期,如即将超过有效期,还会自动续期。</p>
<h3 id="部署cert-manager"><a href="#部署cert-manager" class="headerlink" title="部署cert-manager"></a>部署cert-manager</h3><p>部署cert-manager还是比较简单的,直接用helm部署就可以了</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">helm install \</span><br><span class="line"> --name cert-manager \</span><br><span class="line"> --namespace kube-system \</span><br><span class="line"> stable/cert-manager</span><br></pre></td></tr></table></figure>
</summary>
<category term="k8s" scheme="http://www.chenfanlinux.org/categories/k8s/"/>
<category term="k8s" scheme="http://www.chenfanlinux.org/tags/k8s/"/>
</entry>
<entry>
<title>Git学习笔记</title>
<link href="http://www.chenfanlinux.org/2019/02/23/Git%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<id>http://www.chenfanlinux.org/2019/02/23/Git学习笔记/</id>
<published>2019-02-23T12:15:40.000Z</published>
<updated>2019-03-15T14:58:56.000Z</updated>
<content type="html"><![CDATA[<h2 id="一、git安装管理"><a href="#一、git安装管理" class="headerlink" title="一、git安装管理"></a>一、git安装管理</h2><blockquote><p>Git是分布式的版本控制系统,我们只要有了一个原始Git版本仓库,就可以让其他主机克隆走这个原始版本仓库,从而使得一个Git版本仓库可以被同时分布到不同的主机之上,并且每台主机的版本库都是一样的,没有主次之分,极大的保证了数据安全性,并使得用户能够自主选择向那个Git服务器推送文件了,其实部署一个git服务器是非常简单的。</p><h3 id="1-Git安装部署"><a href="#1-Git安装部署" class="headerlink" title="1.Git安装部署"></a>1.Git安装部署</h3></blockquote><p>1.1 <strong>安装Git</strong></p><pre><code>[root@git-node1 ~]# yum install git -y</code></pre><p>1.2 <strong>配置git全局用户以及邮箱</strong></p><pre><code>[root@git-node1 ~]# git config --global user.name "chenfan" [root@git-node1 ~]# git config --global user.email "1144102576@qq.com" [root@git-node1 ~]# git config --global color.ui true</code></pre><p>1.3 <strong>检查git相关配置</strong></p><pre><code>[root@git-node1 ~]# git config --listuser.name=chenfanuser.email=1144102576@qq.comcolor.ui=true</code></pre><a id="more"></a><h2 id="二、git数据管理"><a href="#二、git数据管理" class="headerlink" title="二、git数据管理"></a>二、git数据管理</h2><h3 id="概要"><a href="#概要" class="headerlink" title="概要"></a><em>概要</em></h3><ol><li>提交数据</li><li>移除数据</li><li>移动数据</li><li>历史数据</li><li>还原数据</li><li>基础操作小结</li></ol><h3 id="1-提交数据"><a href="#1-提交数据" class="headerlink" title="1. 提交数据"></a>1. 提交数据</h3><blockquote><p>我们可以简单的把工作目录理解成是一个被Git服务程序管理的目录,Git会时刻的追踪目录内文件的改动,另外在安装好了Git服务程序后,默认就会创建好了一个叫做master的分支,我们直接可以提交数据。</p></blockquote><h4 id="1-1-创建本地工作目录demo,并初始化为git工作目录"><a href="#1-1-创建本地工作目录demo,并初始化为git工作目录" class="headerlink" title="1.1 创建本地工作目录demo,并初始化为git工作目录"></a>1.1 创建本地工作目录demo,并初始化为git工作目录</h4><pre><code>[root@git-node1 ~]# mkdir demo[root@git-node1 ~]# cd demo/[root@git-node1 git-demo]# git initInitialized empty Git repository in /root/demo/.git/</code></pre><h4 id="1-2-创建readme-txt文件"><a href="#1-2-创建readme-txt文件" class="headerlink" title="1.2 创建readme.txt文件"></a>1.2 创建readme.txt文件</h4><pre><code>[root@git-node1 demo]# touch readme.txt</code></pre><h4 id="1-3-查看git状态"><a href="#1-3-查看git状态" class="headerlink" title="1.3 查看git状态"></a>1.3 查看git状态</h4><pre><code>[root@git-node1 demo]# git status# 位于分支 master## 初始提交## 未跟踪的文件:# (使用 "git add <file>..." 以包含要提交的内容)## readme.txt提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)</code></pre><h4 id="1-4-提示使用git-add添加文件至暂存区"><a href="#1-4-提示使用git-add添加文件至暂存区" class="headerlink" title="1.4 提示使用git add添加文件至暂存区"></a>1.4 提示使用git add添加文件至暂存区</h4><pre><code>[root@git-node1 demo]# git add readme.txt[root@git-node1 demo]# git status //查看变更状态# 位于分支 master## 初始提交## 要提交的变更:# (使用 "git rm --cached <file>..." 撤出暂存区)## 新文件: </code></pre><p>####1.5 使用git commit提交暂存区文件至git版本仓库<br>-m:提交描述信息(提交至远程需添加远程仓库) </p><pre><code>[root@git-node1 demo]# git commit -m "the first commit readme.txt"[master(根提交) 85bd268] the first commit readme.txt 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 readme.txt</code></pre><h3 id="2-移除数据"><a href="#2-移除数据" class="headerlink" title="2. 移除数据"></a>2. 移除数据</h3><blockquote><p>有些时候会将已经添加到暂存区的文件移除,但仍然希望文件在工作目录中不丢失,换句话说,就是把文件从追踪清单中删除。</p></blockquote><h4 id="2-1-建立新文件"><a href="#2-1-建立新文件" class="headerlink" title="2.1 建立新文件"></a>2.1 建立新文件</h4><pre><code>[root@git-node1 demo]# touch index.php</code></pre><h4 id="2-2-添加新文件至暂存区"><a href="#2-2-添加新文件至暂存区" class="headerlink" title="2.2 添加新文件至暂存区"></a>2.2 添加新文件至暂存区</h4><pre><code>[root@git-node1 demo]# git add index.php[root@git-node1 demo]# git status# 位于分支 master# 要提交的变更:# (使用 "git reset HEAD <file>..." 撤出暂存区)## 新文件: index.php</code></pre><h4 id="2-3-将新文件从暂存区撤出-并不会删除工作目录内的数据"><a href="#2-3-将新文件从暂存区撤出-并不会删除工作目录内的数据" class="headerlink" title="2.3 将新文件从暂存区撤出(并不会删除工作目录内的数据)"></a>2.3 将新文件从暂存区撤出(并不会删除工作目录内的数据)</h4><pre><code>[root@git-node1 demo]# git reset HEAD index.php[root@git-node1 demo]# git status //index.php文件状态为未跟踪# 位于分支 master# 未跟踪的文件:# (使用 "git add <file>..." 以包含要提交的内容)## index.php提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)如果想将文件数据从git暂存区和工作目录一起删除,可以做如下操作。[root@git-node1 demo]# git add index.php[root@git-node1 demo]# git rm index.php //文件存已经放入暂存区域,防止误删error: 'index.php' 有变更已暂存至索引中(使用 --cached 保存文件,或用 -f 强制删除)[root@git-node1 demo]# git rm -f index.php //使用追加强制删除-f参数。或者—cache保存rm 'index.php'[root@git-node1 demo]# git status //查看当前状态# 位于分支 master无文件要提交,干净的工作区[root@git-node1 demo]# ls //index.php文件已经被删除index.html</code></pre><h4 id="2-4-丢弃工作目录中的更改"><a href="#2-4-丢弃工作目录中的更改" class="headerlink" title="2.4 丢弃工作目录中的更改"></a>2.4 丢弃工作目录中的更改</h4><blockquote><p>这里举例readme.txt文件已经提交,然后在工作区对readme.txt文件进行修改,在没有add添加到缓存区时,如何进行版本回退。</p></blockquote><pre><code>[root@Centos-6 test]# cat readme.txt 1 hehe2 hehe2 woshihehe3 hehe#增加一行内容变为[root@Centos-6 test]# cat readme.txt 1 hehe2 hehe2 woshihehe3 hehe4 testhehe#git状态发生变化 [root@Centos-6 test]# git status # On branch master# Changed but not updated:# (use "git add <file>..." to update what will be committed)# (use "git checkout -- <file>..." to discard changes in working directory)## modified: readme.txt#no changes added to commit (use "git add" and/or "git commit -a")#这样可以丢弃工作目录中的更改 [root@Centos-6 test]# git checkout -- readme.txt [root@Centos-6 test]# cat readme.txt 1 hehe2 hehe2 woshihehe3 hehe</code></pre><h4 id="2-5-删除远程仓库(比如GitHub)的目录或文件"><a href="#2-5-删除远程仓库(比如GitHub)的目录或文件" class="headerlink" title="2.5 删除远程仓库(比如GitHub)的目录或文件"></a>2.5 删除远程仓库(比如GitHub)的目录或文件</h4><blockquote><p>这来我们想删除远程仓库中的deploy.sh </p></blockquote><pre><code>#从提交状态到缓存区状态 [root@Centos-6 test]# git rm -f deploy.sh rm 'deploy.sh'[root@Centos-6 test]# [root@Centos-6 test]# [root@Centos-6 test]# git status # On branch master# Changes to be committed:# (use "git reset HEAD <file>..." to unstage)## deleted: deploy.sh##从缓存区提交本地仓库[root@Centos-6 test]# git commit -m "delete deploy.sh"[master 20c31fe] delete deploy.sh 1 files changed, 0 insertions(+), 1 deletions(-) delete mode 100644 deploy.sh[root@Centos-6 test]# [root@Centos-6 test]# [root@Centos-6 test]# git status # On branch masternothing to commit (working directory clean)#开始推送到远程仓库[root@Centos-6 test]# git push origin master Counting objects: 3, done.Compressing objects: 100% (2/2), done.Writing objects: 100% (2/2), 221 bytes, done.Total 2 (delta 1), reused 0 (delta 0)remote: Resolving deltas: 100% (1/1), completed with 1 local object.To git@github.com:chenfanfanfan/demo.git 5b832d4..20c31fe master -> master</code></pre><h3 id="3-移动数据"><a href="#3-移动数据" class="headerlink" title="3. 移动数据"></a>3. 移动数据</h3><blockquote><p>有些时候会将已经添加到暂存区的文件重新修改名称,可使用如下操作完成。 </p></blockquote><h4 id="3-1-git重新命名文件名称,使用git-mv操作。"><a href="#3-1-git重新命名文件名称,使用git-mv操作。" class="headerlink" title="3.1 git重新命名文件名称,使用git mv操作。"></a>3.1 git重新命名文件名称,使用git mv操作。</h4><pre><code>[root@git-node1 demo]# git mv index.html index.php</code></pre><h4 id="3-2-使用git-status查看更改状态"><a href="#3-2-使用git-status查看更改状态" class="headerlink" title="3.2 使用git status查看更改状态"></a>3.2 使用git status查看更改状态</h4><pre><code>[root@git-node1 demo]# git status# 位于分支 master# 要提交的变更:# (使用 "git reset HEAD <file>..." 撤出暂存区)## 重命名: index.html -> index.php#</code></pre><h4 id="3-3-使用git-commit-提交git仓库-并描述提交信息"><a href="#3-3-使用git-commit-提交git仓库-并描述提交信息" class="headerlink" title="3.3 使用git commit 提交git仓库,并描述提交信息"></a>3.3 使用git commit 提交git仓库,并描述提交信息</h4><pre><code>[root@git-node1 demo]# git commit -m "chnged name index.html->index.php"[master 9573413] chnged name index.html->index.php 1 file changed, 0 insertions(+), 0 deletions(-) rename index.html => index.php (100%)</code></pre><h3 id="4-历史数据"><a href="#4-历史数据" class="headerlink" title="4. 历史数据"></a>4. 历史数据</h3><blockquote><p>在提交了若干更新之后,想回顾下提交历史,可以使用 git log 命令查看提交历史记录。 </p></blockquote><h4 id="4-1-查看提交历史记录"><a href="#4-1-查看提交历史记录" class="headerlink" title="4.1 查看提交历史记录"></a>4.1 查看提交历史记录</h4><pre><code>[root@git-node1 demo]# git logcommit 95734131860ef7c9078b8a208ff6437d0952380bAuthor: chenfan <1144102576>Date: Sun Nov 6 02:15:35 2016 +0800chnged name index.html->index.phpcommit 85bd2680bd4b70aeded9dbd230c07ab086712ff9Author: chenfan <1144102576@qq.com>Date: Sun Nov 6 01:51:22 2016 +0800the first commit index.html</code></pre><h4 id="4-2-查看历史2次提交记录"><a href="#4-2-查看历史2次提交记录" class="headerlink" title="4.2 查看历史2次提交记录"></a>4.2 查看历史2次提交记录</h4><pre><code>[root@git-node1 demo]# git log -10commit 95734131860ef7c9078b8a208ff6437d0952380bAuthor: chenfan <1144102576@qq.com>Date: Sun Nov 6 02:15:35 2016 +0800chnged name index.html->index.phpcommit 85bd2680bd4b70aeded9dbd230c07ab086712ff9Author:chenfan <1144102576@qq.com>Date: Sun Nov 6 01:51:22 2016 +0800the first commit index.html</code></pre><h4 id="4-3-显示提交的内容差异-例如仅查看最近一次差异"><a href="#4-3-显示提交的内容差异-例如仅查看最近一次差异" class="headerlink" title="4.3 显示提交的内容差异,例如仅查看最近一次差异"></a>4.3 显示提交的内容差异,例如仅查看最近一次差异</h4><pre><code>[root@git-node1 demo]# git log -p -2commit 95734131860ef7c9078b8a208ff6437d0952380bAuthor: chenfan <1144102576@qq.com>Date: Sun Nov 6 02:15:35 2016 +0800chnged name index.html->index.phpdiff --git a/index.html b/index.htmldeleted file mode 100644index e69de29..0000000diff --git a/index.php b/index.phpnew file mode 100644index 0000000..e69de29commit 85bd2680bd4b70aeded9dbd230c07ab086712ff9Author: chenfan <1144102576@qq.com>Date: Sun Nov 6 01:51:22 2016 +0800the first commit index.htmldiff --git a/index.html b/index.htmlnew file mode 100644index 0000000..e69de29</code></pre><h4 id="4-4-根据不同的格式展示提交的历史信息"><a href="#4-4-根据不同的格式展示提交的历史信息" class="headerlink" title="4.4 根据不同的格式展示提交的历史信息"></a>4.4 根据不同的格式展示提交的历史信息</h4><pre><code>[root@git-node1 demo]# git log --pretty=oneline95734131860ef7c9078b8a208ff6437d0952380b chnged name index.html->index.php85bd2680bd4b70aeded9dbd230c07ab086712ff9 the first commit index.htm可以使用format参数来指定具体的输出格式,这样非常便于后期编程的提取分析哦,常用的格式有:%s 提交说明。%cd 提交日期。%an 作者的名字。%cn 提交者的姓名。%ce 提交者的电子邮件。%H 提交对象的完整SHA-1哈希字串。%h 提交对象的简短SHA-1哈希字串。%T 树对象的完整SHA-1哈希字串。%t 树对象的简短SHA-1哈希字串。%P 父对象的完整SHA-1哈希字串。%p 父对象的简短SHA-1哈希字串。%ad 作者的修订时间。定制详细的日志输出[root@git-node1 demo]# git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset %cn"' --abbrev-commit --date=relative* 5f3f588 - (HEAD, origin/master, –r, tt, master) merge branch linux readme.txt (68 分钟之前) xulia|\ | * 4580c3b - (linux) touch readme.txt (80 分钟之前) xuliangwei"* | 4c7a145 - touch readme.txt (72 分钟之前) xuliangwei"|/ * 9573413 - (tag: v1.0.0) chnged name index.html->index.php (5 小时之前) xuliangwei"* 85bd268 - the first commit index.html (5 小时之前) xuliangwei"配置.git/config文件,增加如下2行,以后即可使用 git hlog代替如上复杂命令[root@git-node1 demo]# tail -2 .git/config [alias] hlog = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset %cn' --abbrev-commit --date=relative //以后使用git hlog即可实现复杂的命令</code></pre><h3 id="5-还原数据"><a href="#5-还原数据" class="headerlink" title="5. 还原数据"></a>5. 还原数据</h3><blockquote><p>将文件boss good写成了boss dou,但是已经提交至远程仓库,现在想要撤回重新提交。<br>(本小结涉及远程仓库,可先学习后面章节,在回头学习本章节) </p></blockquote><h4 id="5-1-查看index-html文件"><a href="#5-1-查看index-html文件" class="headerlink" title="5.1 查看index.html文件"></a>5.1 查看index.html文件</h4><pre><code>[root@git-node1 demo]# git checkout -b dev //内容存在dev分支[root@git-node1 demo]# cat index.htmlhello boss</code></pre><h4 id="5-2-追加内容至index-html,并提交至远程仓库"><a href="#5-2-追加内容至index-html,并提交至远程仓库" class="headerlink" title="5.2 追加内容至index.html,并提交至远程仓库"></a>5.2 追加内容至index.html,并提交至远程仓库</h4><pre><code>[root@git-node1 demo]# echo "boos doubi" >> index.html [root@git-node1 demo]# git add index.html[root@git-node1 demo]# git commit -m "boss dou"[master 1941990] boss dou 1 file changed, 1 insertion(+)[root@git-node1 demo]# git push origin devCounting objects: 5, done.Compressing objects: 100% (2/2), done.Writing objects: 100% (3/3), 298 bytes | 0 bytes/s, done.Total 3 (delta 0), reused 0 (delta 0)To git@git-node1:root/git_demo.git 507bf99..1941990 dev -> dev</code></pre><h4 id="5-3-此时觉得写的不妥,想还原上一次提交的文件快照,找出历史信息"><a href="#5-3-此时觉得写的不妥,想还原上一次提交的文件快照,找出历史信息" class="headerlink" title="5.3 此时觉得写的不妥,想还原上一次提交的文件快照,找出历史信息"></a>5.3 此时觉得写的不妥,想还原上一次提交的文件快照,找出历史信息</h4><pre><code>[root@git-node1 demo]# git hlog -2* 1941990 - (HEAD, origin/dev, dev) boss dou (2 分钟之前) xuliangwei* 507bf99 - hello (30 分钟之前) xuliangwei</code></pre><h4 id="5-4-找到历史还原点的值后,就可以还原-值不写全-系统会自动匹配"><a href="#5-4-找到历史还原点的值后,就可以还原-值不写全-系统会自动匹配" class="headerlink" title="5.4 找到历史还原点的值后,就可以还原(值不写全,系统会自动匹配)"></a>5.4 找到历史还原点的值后,就可以还原(值不写全,系统会自动匹配)</h4><pre><code>[root@git-node1 demo]# git reset --hard 507bf99HEAD 现在位于 507bf99 hello[root@git-node1 xuliangwei]# git push origin dev -f //强制推送至dev分支[root@git-node1 demo]# cat index.htmlhello boss</code></pre><p>工作区—-缓存区—-本地仓库—-远程仓库</p><p>工作区—->缓存区 git add filename </p><p>缓存区—->工作区 git reset HEAD filename</p><p>缓存区—->本地仓库 git commit -m “add filename”</p><p>本地仓库—->缓存区 git rm filename </p><p>本地仓库—->工作区 git rm -f filename git commit -m “delete filename” </p><p>远程仓库—->本地仓库 git pull origin master</p><p>本地仓库—->远程仓库 git push origin master -f </p><h3 id="6-git基本命令操作小结"><a href="#6-git基本命令操作小结" class="headerlink" title="6. git基本命令操作小结"></a>6. git基本命令操作小结</h3><blockquote><p>相信大家对Git的基本操作有一定的了解,下面进行一下简单的梳理总结:</p></blockquote><p>命令 git config –global user.name “name” #配置git使用用户</p><p>git config –global user.email “mail” #配置git使用邮箱</p><p>git config –global color.ui true #配置颜色</p><p>git config –list #查看当前配置</p><p>git init #初始为git工作目录</p><p>git status #查看git状态</p><p>git reflog #查看未来历史更新点</p><p>git reset –hard 4bf5b29 #找到历史还原点的SHA-1值,就可以还原(值不写全,系统会自动匹配)</p><p>git checkout – file #恢复暂存区至上一版本</p><p>git add [file1] [file2] … #添加指定文件至暂存区</p><p>git add [dir] #添加指定目录至暂存区,包括子目录(递归添加)</p><p>git add . #添加当前目录所有文件至暂存区</p><p>git rm [file1] [file2] … #删除工作区文件,并将这次删除放入暂存区</p><p>git rm -cached [file] #停止追踪指定文件,但该文件会保留在工作区</p><p>git mv [file-old] [file-new] #重命名文件,修改后放入暂存区</p><h2 id="三、git仓库管理"><a href="#三、git仓库管理" class="headerlink" title="三、git仓库管理"></a>三、git仓库管理</h2><blockquote><p>现在本地已经创建了git仓库,又在gitlab上创建了一个git仓库,并且让这两个仓库进行远程同步,这样gitlab仓库既可以备份也可以与他人协作管理远程仓库以及根据需要推送或拉取数据。<br>管理远程仓库包括了如何添加远程仓库、移除无用远程仓库、查看远程仓库、修改远程仓库等等</p><h3 id="概要-1"><a href="#概要-1" class="headerlink" title="概要"></a><em>概要</em></h3></blockquote><ol><li>部署开源仓库</li><li>添加远程仓库</li><li>修改远程仓库</li><li>查看远程仓库</li><li>推送远程仓库</li><li>克隆远程仓库</li><li>拉取远程仓库</li><li>移除远程仓库</li><li>Git远程仓库小结</li></ol><h3 id="1-部署开源仓库"><a href="#1-部署开源仓库" class="headerlink" title="1. 部署开源仓库"></a>1. 部署开源仓库</h3><blockquote><p>GitLab 是一个用于仓库管理系统的开源项目。</p></blockquote><p>####1.1 安装配置gitlab依赖项 </p><blockquote><p>如想使用Postfix来发送邮件,在安装期间请选择’Internet Site’. 您也可以用sendmai或者 配置SMTP服务并使用SMTP发送邮件.在 Centos7系统上,下面的命令将在系统防火墙里面开放HTTP和SSH端口.</p></blockquote><pre><code>[root@git-node1 ~]# yum -y install curl openssh-server postfix[root@git-node1 ~]# /etc/init.d/postfix start </code></pre><h4 id="1-2-添加GitLab仓库-并安装到服务器"><a href="#1-2-添加GitLab仓库-并安装到服务器" class="headerlink" title="1.2 添加GitLab仓库,并安装到服务器"></a>1.2 添加GitLab仓库,并安装到服务器</h4><pre><code>[root@git-node1 ~]# curl -sS http://packages.gitlab.cc/install/gitlab-ce/script.rpm.sh | bash[root@git-node1 ~]# nohup yum -y install gitlab-ce & </code></pre><h4 id="1-3-启动GitLab"><a href="#1-3-启动GitLab" class="headerlink" title="1.3 启动GitLab"></a>1.3 启动GitLab</h4><pre><code>gitlab-ctl reconfigure</code></pre><h4 id="1-4-配置gitlab主机名"><a href="#1-4-配置gitlab主机名" class="headerlink" title="1.4 配置gitlab主机名"></a>1.4 配置gitlab主机名</h4><blockquote><p>修改配置文件/etc/gitlab/gitlab.rb,修改external_url为部署机器的域名或者主机名</p></blockquote><pre><code>[root@chenfan@gitlab ~]# cat /etc/gitlab/gitlab.rb |grep -v '#'|grep 'external_url'external_url 'http://chenfan.gitlab.com'</code></pre><blockquote><p>修改配置文件/var/opt/gitlab/gitlab-rails/etc/gitlab.yml</p></blockquote><pre><code>[root@chenfan@gitlab ~]#cat /var/opt/gitlab/gitlab-rails/etc/gitlab.yml|grep host host: chenfan.gitlab.com</code></pre><blockquote><p>修改配置后重新生效</p></blockquote><pre><code>[root@chenfan@gitlab ~]# gitlab-ctl reconfigure</code></pre><h4 id="1-5-添加远程仓库"><a href="#1-5-添加远程仓库" class="headerlink" title="1.5 添加远程仓库"></a>1.5 添加远程仓库</h4><p>1.5.1 gitlab创建仓库,进行远程同步,如图所示<br><img src="https://cdn-std.dprcdn.net/files/acc_582513/gb3rxN" alt="gitlab创建远程仓库"></p><p>1.5.2 使用git remote 添加远程仓库地址,选择SSH方式克隆。</p><pre><code>方法1:[root@chenfan@gitlab test-demo]# git clone git@chenfan.gitlab.com:root/test-demo.git[root@chenfan@gitlab test-demo]# touch readme.md[root@chenfan@gitlab test-demo]# vim readme.md [root@chenfan@gitlab test-demo]# git status [root@chenfan@gitlab test-demo]# git add readme.md[root@chenfan@gitlab test-demo]# git status [root@chenfan@gitlab test-demo]# git commit -m "first commit readme.md"方法2:[root@chenfan@gitlab ~]# mkdir test-gitlab [root@chenfan@gitlab ~]# cd test-gitlab/[root@chenfan@gitlab test-gitlab]# git init[root@chenfan@gitlab test-gitlab]# git remote add origin git@chenfan.gitlab.com:root/test-demo.git</code></pre><h4 id="1-6-推送远程仓库"><a href="#1-6-推送远程仓库" class="headerlink" title="1.6 推送远程仓库"></a>1.6 推送远程仓库</h4><blockquote><p>将本地库更新内容推送至远程,用git push命令,实际上是将当前分支推送至远程仓库。<br>由于远程库是新建立空的,我们在第一次推送时候,git默认是不会把本地master关联至远端的master,所以我们需要加上-u参数,这样git不但会把本地的master分支内容推送至远程仓库的master分支,并且还会将本地的master分支和远程master分支关联起来。在以后推送或者拉取时就可以简化命令。分支 master 设置为跟踪来自 origin 的远程分支 master。</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git push -u origin master Counting objects: 3, done.Writing objects: 100% (3/3), 230 bytes, done.Total 3 (delta 0), reused 0 (delta 0)To git@chenfan.gitlab.com:root/test-demo.git * [new branch] master -> masterBranch master set up to track remote branch master from origin.//分支 master 设置为跟踪来自 origin 的远程分支 master</code></pre><blockquote><p>如果推送冲突可以选择–force强行推送</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git push origin --force如果一次都没有推送数据,可以选择—all一次全部推送至远程服务器[root@chenfan@gitlab test-demo]# git push origin --all</code></pre><h4 id="1-7-克隆远程仓库"><a href="#1-7-克隆远程仓库" class="headerlink" title="1.7 克隆远程仓库"></a>1.7 克隆远程仓库</h4><blockquote><p>如果现在仓库已经有开发好的项目,需要加入进来开发,可以先clone整个项目。</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]#git clone git@chenfan.gitlab.com:root/test-demo.git</code></pre><h4 id="1-8-拉取远程仓库"><a href="#1-8-拉取远程仓库" class="headerlink" title="1.8 拉取远程仓库"></a>1.8 拉取远程仓库</h4><blockquote><p>简单的说,这个命令会访问远程仓库,从中取出你还没有的数据,或者git pull之后还是没有的数据。<br>此前在添加的远程仓库的时候指定了仓库名origin,命令会自动将其添加为远程仓库并默认以origin为简写。 所以,git fetch origin相当于从远程获取最新版本到本地,然后比较本地master分支和远程master分支差别最后进行合并。</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git fetch origin //拉取主分支最新版本(可以拉取其他分支)</code></pre><blockquote><p>拉取数据,在生产环境中见到比较多的还是git pull相当于是从远程获取最新版本并merge到本地</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git pull origin master From chenfan.gitlab.com:root/test-demo * branch master -> FETCH_HEADAlready up-to-date.</code></pre><blockquote><p>上述命令其实相当于git fetch 和 git merge在实际使用中,git fetch更安全一些,因为在merge前,我们可以查看更新情况,然后再决定是否合并。</p></blockquote><h4 id="1-9-更改远程仓库名"><a href="#1-9-更改远程仓库名" class="headerlink" title="1.9 更改远程仓库名"></a>1.9 更改远程仓库名</h4><blockquote><p>如果想重新命名一个远程仓库名称。将test重命名为rainbow,可以通过git remote rename进行修改。 意:这同时会修改你的远程分支名字。之前引用test/master的现在会引用rainbow/master</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git remote add test git@chenfan.gitlab.com:root/test-demo.git[root@chenfan@gitlab test-demo]# [root@chenfan@gitlab test-demo]# [root@chenfan@gitlab test-demo]# git remote -v origin git@chenfan.gitlab.com:root/test-demo.git (fetch)origin git@chenfan.gitlab.com:root/test-demo.git (push)test git@chenfan.gitlab.com:root/test-demo.git (fetch)test git@chenfan.gitlab.com:root/test-demo.git (push)</code></pre><blockquote><p>修改test名称为rainbow名称</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git remote rename test rainbow [root@chenfan@gitlab test-demo]# git remote -v origin git@chenfan.gitlab.com:root/test-demo.git (fetch)origin git@chenfan.gitlab.com:root/test-demo.git (push)rainbow git@chenfan.gitlab.com:root/test-demo.git (fetch)rainbow git@chenfan.gitlab.com:root/test-demo.git (push)</code></pre><h4 id="1-10-移除远程仓库"><a href="#1-10-移除远程仓库" class="headerlink" title="1.10 移除远程仓库"></a>1.10 移除远程仓库</h4><blockquote><p>因为一些变动不再使用一些特定的镜像,可以通过git remote remove 远程仓库名称,移除远程仓库。</p></blockquote><p><strong>查看远程仓库</strong></p><pre><code>[root@chenfan@gitlab test-demo]# git remote -v origin git@chenfan.gitlab.com:root/test-demo.git (fetch)origin git@chenfan.gitlab.com:root/test-demo.git (push)rainbow git@chenfan.gitlab.com:root/test-demo.git (fetch)rainbow git@chenfan.gitlab.com:root/test-demo.git (push)</code></pre><p><strong>移除不再使用的rainbow远程仓库</strong></p><pre><code>[root@chenfan@gitlab test-demo]# git remote rm rainbow[root@chenfan@gitlab test-demo]# [root@chenfan@gitlab test-demo]# [root@chenfan@gitlab test-demo]# git remote -v origin git@chenfan.gitlab.com:root/test-demo.git (fetch)origin git@chenfan.gitlab.com:root/test-demo.git (push)</code></pre><h4 id="1-11-Git远程仓库小结"><a href="#1-11-Git远程仓库小结" class="headerlink" title="1.11 Git远程仓库小结"></a>1.11 Git远程仓库小结</h4><blockquote><p>要添加一个仓库,首先必须知道仓库的地址,然后使用git remote add 命令添加远程仓库,也可使用git clone命令克隆。(Git支持多种协议,包括http、https,但通过ssh支持的原生git协议速度最佳。)<br>要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git,关联后,使用命令git push -u origin master第一次推送master分支的所有内容,此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改</p></blockquote><pre><code># git remote add [remote] [url]#添加(关联)远程库# git remote set-url [remote] [url] #修改远程仓库# git clone [url] #克隆远程仓库项目# git remote #查看指定远程仓库命名简写# git remote –v #查看远程仓库详细信息以及名称对应URL# git push -u remote master #第一次推送master分支的所有内容# git fetch remote [branch/tag] #下载远程仓库的所有变动# git pull remote [branch/tag] #拉取主分支最新版本(可以拉取其他分支)# git push remote [branch/tag] --force #强行推送当前分支至远程分支,及时冲突# git push remote [branch/tag] --all #推送所有分支到远程仓库# git remote rename [oldname] [newname] #修改远程仓库名称# git remote rm [name] #删除远程仓库名称以及URL地址</code></pre><p>##四.Git分支管理</p><p>###概要</p><ol><li>Git分支管理</li><li>创建本地分支</li><li>切换本地分支</li><li>合并本地分支</li><li>删除本地分支</li><li>查看远程分支</li><li>解决分支冲突</li><li>删除远程分支</li><li>Git分支小结</li></ol><h3 id="1-Git分支管理"><a href="#1-Git分支管理" class="headerlink" title="1.Git分支管理"></a>1.Git分支管理</h3><blockquote><p>分支即是平行空间,假设你在为某个手机系统研发拍照功能,代码已经完成了80%,但如果将这不完整的代码直接提交到git仓库中,又有可能影响到其他人的工作,此时我们便可以在该软件的项目之上创建一个名叫“拍照功能”的分支,这种分支只会属于你自己,而其他人看不到,等代码编写完成后再与原来的项目主分支合并下即可,这样即能保证代码不丢失,又不影响其他人的工作。</p></blockquote><p><img src="https://cdn-std.dprcdn.net/files/acc_582513/YDfaGs" alt="gitlab分支管理" title="gitlab分支管理"><br><strong>gitlab团队合作流程图</strong></p><blockquote><p>一般在实际的项目开发中,我们要尽量保证master分支是非常稳定的,仅用于发布新版本,平时不要随便直接修改里面的数据文件,而工作的时候则可以新建不同的工作分支,等到工作完成后在合并到master分支上面,所以团队的合作分支看起来会像上面图那样。</p></blockquote><p><img src="https://cdn-std.dprcdn.net/files/acc_582513/cggckI" alt="git分支示意图" title="gitlab分支示意图"><br><strong>gitlab分支示意图</strong></p><h3 id="2-创建本地分支"><a href="#2-创建本地分支" class="headerlink" title="2.创建本地分支"></a>2.创建本地分支</h3><blockquote><p>首先创建本地dev分支</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git branch dev //创建dev分支[root@chenfan@gitlab test-demo]# git branch //查看分支 dev* master</code></pre><h3 id="3-切换本地分支"><a href="#3-切换本地分支" class="headerlink" title="3.切换本地分支"></a>3.切换本地分支</h3><blockquote><p>切换分支至刚建立dev分支</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git checkout dev //切换分支Switched to branch 'dev'# //查看分支情况[root@chenfan@gitlab test-demo]# git branch* dev master</code></pre><blockquote><p>切换分支发生冲突会导致无法切换对应分支,可使用-f强制切换</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git checkout -f master //强制切换分支Switched to branch 'master'[root@chenfan@gitlab test-demo]# git branch dev* master</code></pre><h3 id="4-合并本地分支"><a href="#4-合并本地分支" class="headerlink" title="4.合并本地分支"></a>4.合并本地分支</h3><blockquote><p>现在,我们想把linux的工作成果合并到master分支上了,则可以使用”git merge”命令来将指定的的分支与当前分支合并 。</p></blockquote><p><img src="https://cdn-std.dprcdn.net/files/acc_582513/dnX9wc" alt="合并分支"><br><strong>合并分支示意图</strong></p><pre><code>[root@chenfan@gitlab test-demo]# git branch dev* master[root@chenfan@gitlab test-demo]# git checkout dev Switched to branch 'dev'[root@chenfan@gitlab test-demo]# git branch* dev master[root@chenfan@gitlab test-demo]# echo "create branch dev">index.html[root@chenfan@gitlab test-demo]# git add index.html[root@chenfan@gitlab test-demo]# git commit -m "new branch dev"[root@chenfan@gitlab test-demo]# git checkout master[root@chenfan@gitlab test-demo]# git merge dev Updating 27759b5..230c227Fast-forward index.html | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 index.html</code></pre><h3 id="5-删除本地分支"><a href="#5-删除本地分支" class="headerlink" title="5.删除本地分支"></a>5.删除本地分支</h3><blockquote><p>合并完成dev分支后,可以放心的删除。</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git branch -d dev [root@chenfan@gitlab test-demo]# git branch //查看本地分支 * master</code></pre><h3 id="6-查看远程分支"><a href="#6-查看远程分支" class="headerlink" title="6. 查看远程分支"></a>6. 查看远程分支</h3><pre><code>[root@chenfan@gitlab test-demo]# git branch -a //查看远程分支* master remotes/origin/master</code></pre><h3 id="7-解决分支冲突"><a href="#7-解决分支冲突" class="headerlink" title="7.解决分支冲突"></a>7.解决分支冲突</h3><blockquote><p>但是Git并不能每次都为我们自动的合并分支,当遇到了内容冲突比较复杂的情况,则必须手工将差异内容处理点,比如这样的情况:</p></blockquote><p><img src="https://cdn-std.dprcdn.net/files/acc_582513/f7NwLN" alt="gitlab分支冲突"><br><strong>分支冲突情况</strong></p><h4 id="7-1-创建linux分支并切换到linux分支"><a href="#7-1-创建linux分支并切换到linux分支" class="headerlink" title="7.1 创建linux分支并切换到linux分支"></a>7.1 创建linux分支并切换到linux分支</h4><pre><code>[root@chenfan@gitlab test-demo]# git checkout -b linux //创建新的分支并切换到新分支下Switched to a new branch 'linux'</code></pre><h4 id="7-2-添加1行内容,并推送到远程仓库"><a href="#7-2-添加1行内容,并推送到远程仓库" class="headerlink" title="7.2 添加1行内容,并推送到远程仓库"></a>7.2 添加1行内容,并推送到远程仓库</h4><pre><code>[root@chenfan@gitlab test-demo]# echo '1.branch linux'>readme.txt //创建readme.txt[root@chenfan@gitlab test-demo]# git add readme.txt [root@chenfan@gitlab test-demo]# git commit -m "touch readme.txt"[root@chenfan@gitlab test-demo]# git push -u origin linux [root@chenfan@gitlab test-demo]# git branch* linux master</code></pre><h4 id="7-3-切换至master分支,添加readme-txt文件,并和linux分支相同位置,然后尝试合并"><a href="#7-3-切换至master分支,添加readme-txt文件,并和linux分支相同位置,然后尝试合并" class="headerlink" title="7.3 切换至master分支,添加readme.txt文件,并和linux分支相同位置,然后尝试合并"></a>7.3 切换至master分支,添加readme.txt文件,并和linux分支相同位置,然后尝试合并</h4><pre><code>[root@chenfan@gitlab test-demo]# git checkout master //切换到master分支Switched to branch 'master'Your branch is ahead of 'origin/master' by 1 commit.[root@chenfan@gitlab test-demo]# echo "1.branch master" > readme.txt //同样创建readme.txt文件 [root@chenfan@gitlab test-demo]# git add readme.txt [root@chenfan@gitlab test-demo]# git commit -m "add readme.txt master" //提交[root@chenfan@gitlab test-demo]# git merge linux //合并分支开始出现冲突 Auto-merging readme.txtCONFLICT (add/add): Merge conflict in readme.txtAutomatic merge failed; fix conflicts and then commit the result.[root@chenfan@gitlab test-demo]# vim readme.txt //需要手动修改文件<<<<<<< HEAD //去掉1.branch master======= //去掉1.branch linux>>>>>>> linux //去掉[root@chenfan@gitlab test-demo]# cat readme.txt 1.branch master1.branch linux</code></pre><h4 id="7-4-重新提交,推送远程仓库"><a href="#7-4-重新提交,推送远程仓库" class="headerlink" title="7.4 重新提交,推送远程仓库"></a>7.4 重新提交,推送远程仓库</h4><pre><code>[root@chenfan@gitlab test-demo]# git commit -m "add readme.txt" //重新提交[root@chenfan@gitlab test-demo]# git push origin master //推送到远程仓库</code></pre><h3 id="8-删除远程分支"><a href="#8-删除远程分支" class="headerlink" title="8.删除远程分支"></a>8.删除远程分支</h3><blockquote><p>删除如上已经被合并过的linux分支。</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git push origin --delete linux //删除远程分支To git@chenfan.gitlab.com:root/test-demo.git - [deleted] linux[root@chenfan@gitlab test-demo]# git branch -d linux //删除本地分支Deleted branch linux (was e798757).[root@chenfan@gitlab test-demo]# git branch -a * master remotes/origin/master</code></pre><h3 id="9-Git分支小结"><a href="#9-Git分支小结" class="headerlink" title="9.Git分支小结"></a>9.Git分支小结</h3><blockquote><p>Git鼓励大量使用分支<br>常见分支结构<br>dev分支<br>bug分支<br>新功能分支 </p></blockquote><pre><code>命令 git branch //列出所有本地分支命令git branch –r //列出所有远程分支命令git branch –a //列出所有本地分支和远程分支命令git branch [branch-name] //创建新分支命令git checkout –b [branch-name] //创建新分支,并且切换到该分支命令 git branch --track [branch] [remote-branch] //创建新分支,与指定的远程分支建立追踪关系命令 git checkout [branch-name] //切换至指定分支命令 git branch –set-upstream [branch] [remote-branch] //本地分支与远程分支建立追踪关系命令 git merge [branch] //合并指定分支到当前分支命令 git cherry-pick [commit] //选择一个commit,合并至当前分支命令git branch –d [branch-name] //删除本地分支命令git push origin --delete [branch-name] //删除远程分支命令git branch –dr [remote/branch] //删除远程分支</code></pre><p>##五.Git标签管理</p><blockquote><p>当版本仓库内的数据有个大的改善或者功能更新,我们经常会打一个类似于软件版本号的标签,这样通过标签就可以将版本库中的某个历史版本给记录下来,方便我们随时将特定历史时期的数据取出来用,另外打标签其实只是像某个历史版本做了一个指针,所以一般都是瞬间完成的。</p></blockquote><h3 id="概要-2"><a href="#概要-2" class="headerlink" title="概要"></a>概要</h3><ol><li>创建本地标签</li><li>查看本地标签</li><li>删除本地标签</li><li>推送本地标签</li><li>获取远程标签</li><li>删除远程标签</li><li>Git标签小结</li></ol><h3 id="1-创建本地标签"><a href="#1-创建本地标签" class="headerlink" title="1.创建本地标签"></a>1.创建本地标签</h3><blockquote><p>创建带有说明的标签,-a指定标签名字,-m指定说明文字</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git tag -a v1.0.0 -m "version 1.0.0 release "</code></pre><h3 id="2-查看本地标签"><a href="#2-查看本地标签" class="headerlink" title="2.查看本地标签"></a>2.查看本地标签</h3><h4 id="2-1-查看当前本地所有标签"><a href="#2-1-查看当前本地所有标签" class="headerlink" title="2.1 查看当前本地所有标签"></a>2.1 查看当前本地所有标签</h4><pre><code>[root@chenfan@gitlab test-demo]# git tag -l v*v1.0.0</code></pre><h4 id="2-2-查看当前1-0版本的详细信息"><a href="#2-2-查看当前1-0版本的详细信息" class="headerlink" title="2.2 查看当前1.0版本的详细信息"></a>2.2 查看当前1.0版本的详细信息</h4><pre><code>[root@chenfan@gitlab test-demo]# git show v1.0.0tag v1.0.0Tagger: chenfan <1144102576@qq.com>Date: Tue Oct 3 07:55:29 2017 +0800version 1.0.0 releasecommit 5feef6edad5fa5b6ee9a85a49190527be85172acMerge: 86b832e e798757Author: chenfan <1144102576@qq.com>Date: Tue Oct 3 07:32:55 2017 +0800 add test.txt masterdiff --cc test.txtindex 0bf2c1d,f003201..b5d3ebf--- a/test.txt+++ b/test.txt@@@ -1,1 -1,1 +1,2 @@@ +test for master+ test for linux</code></pre><h3 id="3-删除本地标签"><a href="#3-删除本地标签" class="headerlink" title="3.删除本地标签"></a>3.删除本地标签</h3><blockquote><p>我们为同一个提交版本设置了两次标签,删除重复性的标签</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git tag -l v1.0.0v1.0.1[root@chenfan@gitlab test-demo]# git tag -d v1.0.1 Deleted tag 'v1.0.1' (was 5707077)</code></pre><h3 id="4-推送本地标签"><a href="#4-推送本地标签" class="headerlink" title="4.推送本地标签"></a>4.推送本地标签</h3><blockquote><p>如上操作都是基于打标签以及删除标签,下面我们来学习下打完标签后如何推送至远端服务器<br>也可以使用git push origin –-tags推送所有本地建立的tag包</p></blockquote><pre><code>[root@chenfan@gitlab test-demo]# git push origin v1.0.0Counting objects: 1, done.Writing objects: 100% (1/1), 165 bytes, done.Total 1 (delta 0), reused 0 (delta 0)To git@chenfan.gitlab.com:root/test-demo.git * [new tag] v1.0.0 -> v1.0.0</code></pre><h3 id="5-获取远程标签"><a href="#5-获取远程标签" class="headerlink" title="5.获取远程标签"></a>5.获取远程标签</h3><h3 id="6-删除远程标签"><a href="#6-删除远程标签" class="headerlink" title="6.删除远程标签"></a>6.删除远程标签</h3><pre><code>[root@chenfan@gitlab test-demo]# git push origin --delete tag v1.0.0To git@chenfan.gitlab.com:root/test-demo.git - [deleted] v1.0.0也可以先删除本地tag标签,然后推送空标签至于远程进行删除[root@chenfan@gitlab test-demo]# git tag -d v1.0.0[root@chenfan@gitlab test-demo]# git push origin v1.1.0[root@chenfan@gitlab test-demo]# git tag -d v1.1.0[root@chenfan@gitlab test-demo]# git push git push origin :refs/tags/v1.0.1</code></pre><p>7.Git标签小结<br>><br>git版本号规则<br>内部版本 B1.1.0<br>外部版本 V1.1.0<br>补丁版本 P1.1.0 </p><p>命令git tag –a <tagname> -m “message” //在当前commit状态新建一个tag<br>命令git tag -l <tagname> //列出相对应版本号tag<br>命令git push origin <tagname> //推送一个本地标签<br>命令git push origin –tags //推送全部未推送过的本地标签<br>命令git tag -d <tagname> //删除一个本地标签<br>命令git push origin –delete tag <tagname> //删除一个远程标签<br>命令git push origin :refs/tags/<tagname> //删除一个远程标签</tagname></tagname></tagname></tagname></tagname></tagname></p><p>##六.Gitlab备份与恢复、迁移与升级</p><h3 id="概要-3"><a href="#概要-3" class="headerlink" title="概要"></a>概要</h3><ol><li>gitlab备份<br>1.1 gitlab备份目录<br>1.2 gitlab自动备份 </li><li>gitlab恢复</li><li>gitlab迁移</li><li>gitlab升级</li><li>gitlab修改默认nginx </li></ol><h3 id="1-gitlab备份"><a href="#1-gitlab备份" class="headerlink" title="1.gitlab备份"></a>1.gitlab备份</h3><blockquote><p>使用Gitlab一键安装包安装Gitlab非常简单, 同样的备份恢复与迁移也非常简单. 使用一条命令即可创建完整的Gitlab备份:</p></blockquote><pre><code>gitlab-rake gitlab:backup:create</code></pre><blockquote><p>使用以上命令会在/var/opt/gitlab/backups目录下创建一个名称类似为1481598919_gitlab_backup.tar的压缩包, 这个压缩包就是Gitlab整个的完整部分, 其中开头的1481598919是备份创建的日期<br>/etc/gitlab/gitlab.rb 配置文件须备份<br>/var/opt/gitlab/nginx/conf nginx配置文件<br>/etc/postfix/main.cfpostfix 邮件配置备份</p></blockquote><h4 id="1-1-Gitlab备份目录"><a href="#1-1-Gitlab备份目录" class="headerlink" title="1.1 Gitlab备份目录"></a>1.1 Gitlab备份目录</h4><blockquote><p>可以通过/etc/gitlab/gitlab.rb配置文件来修改默认存放备份文件的目录<br> gitlab_rails[‘backup_path’] = “/var/opt/gitlab/backups”<br>/var/opt/gitlab/backups修改为你想存放备份的目录即可, 修改完成之后使用gitlab-ctl reconfigure命令重载配置文件即可.</p></blockquote><h4 id="1-2-Gitlab自动备份"><a href="#1-2-Gitlab自动备份" class="headerlink" title="1.2 Gitlab自动备份"></a>1.2 Gitlab自动备份</h4><blockquote><p>实现每天凌晨2点进行一次自动备份:通过crontab使用备份命令实现</p></blockquote><pre><code>0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create</code></pre><h3 id="2-Gitlab恢复"><a href="#2-Gitlab恢复" class="headerlink" title="2.Gitlab恢复"></a>2.Gitlab恢复</h3><blockquote><p>Gitlab的从备份恢复也非常简单:</p></blockquote><pre><code># 停止相关数据连接服务gitlab-ctl stop unicorngitlab-ctl stop sidekiq# 从1481598919编号备份中恢复gitlab-rake gitlab:backup:restore BACKUP=1481598919# 启动Gitlabsudo gitlab-ctl start</code></pre><h3 id="3-gitlab迁移"><a href="#3-gitlab迁移" class="headerlink" title="3.gitlab迁移"></a>3.gitlab迁移</h3><blockquote><p>迁移如同备份与恢复的步骤一样, 只需要将老服务器/var/opt/gitlab/backups目录下的备份文件拷贝到新服务器上的/var/opt/gitlab/backups即可(如果你没修改过默认备份目录的话).<br>但是需要注意的是新服务器上的Gitlab的版本必须与创建备份时的Gitlab版本号相同. 比如新服务器安装的是最新的7.60版本的Gitlab, 那么迁移之前, 最好将老服务器的Gitlab 升级为7.60在进行备份.<br>/etc/gitlab/gitlab.rb gitlab配置文件须迁移,迁移后需要调整数据存放目录<br>/var/opt/gitlab/nginx/conf nginx配置文件目录须迁移</p></blockquote><pre><code>[root@linux-node1 ~]# gitlab-ctl stop unicornok: down: unicorn: 0s, normally up[root@linux-node1 ~]# gitlab-ctl stop sidekiqok: down: sidekiq: 0s, normally up[root@linux-node1 ~]# chmod 777 /var/opt/gitlab/backups/1481598919_gitlab_backup.tar[root@linux-node1 ~]# gitlab-rake gitlab:backup:restore BACKUP=1481598919</code></pre><h3 id="4-gitlab升级"><a href="#4-gitlab升级" class="headerlink" title="4.gitlab升级"></a>4.gitlab升级</h3><h4 id="4-1-关闭gitlab服务"><a href="#4-1-关闭gitlab服务" class="headerlink" title="4.1 关闭gitlab服务"></a>4.1 关闭gitlab服务</h4><pre><code>gitlab-ctl stop unicorngitlab-ctl stop sidekiqgitlab-ctl stop nginx</code></pre><h4 id="4-2-备份gitlab"><a href="#4-2-备份gitlab" class="headerlink" title="4.2 备份gitlab"></a>4.2 备份gitlab</h4><pre><code>gitlab-rake gitlab:backup:create</code></pre><h4 id="4-3-下载gitlab的RPM包并进行升级"><a href="#4-3-下载gitlab的RPM包并进行升级" class="headerlink" title="4.3 下载gitlab的RPM包并进行升级"></a>4.3 下载gitlab的RPM包并进行升级</h4><pre><code>curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bashyum update gitlab-ce或者直接安装高版本yum install gitlab-ce-8.12.13-ce.0.el7.x86_64或者上官网下载最新版本 gitlab对应软件包 [gitlab官网](https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-8.12.13-ce.0.el7.x86_64.rpm)使用 rpm -Uvh gitlab-ce-8.12.13-ce.0.el7.x86_64报错.Error executing action `run` on resource 'ruby_block[directory resource: /var/opt/gitlab/git-data/repositories]'解决方法:sudo chmod 2770 /var/opt/gitlab/git-data/repositories</code></pre><h4 id="4-4-启动并查看gitlab版本信息"><a href="#4-4-启动并查看gitlab版本信息" class="headerlink" title="4.4 启动并查看gitlab版本信息"></a>4.4 启动并查看gitlab版本信息</h4><pre><code>gitlab-ctl reconfiguregitlab-ctl restart# head -1 /opt/gitlab/version-manifest.txt gitlab-ce 8.7.3</code></pre>]]></content>
<summary type="html">
<h2 id="一、git安装管理"><a href="#一、git安装管理" class="headerlink" title="一、git安装管理"></a>一、git安装管理</h2><blockquote>
<p>Git是分布式的版本控制系统,我们只要有了一个原始Git版本仓库,就可以让其他主机克隆走这个原始版本仓库,从而使得一个Git版本仓库可以被同时分布到不同的主机之上,并且每台主机的版本库都是一样的,没有主次之分,极大的保证了数据安全性,并使得用户能够自主选择向那个Git服务器推送文件了,其实部署一个git服务器是非常简单的。</p>
<h3 id="1-Git安装部署"><a href="#1-Git安装部署" class="headerlink" title="1.Git安装部署"></a>1.Git安装部署</h3></blockquote>
<p>1.1 <strong>安装Git</strong></p>
<pre><code>[root@git-node1 ~]# yum install git -y
</code></pre><p>1.2 <strong>配置git全局用户以及邮箱</strong></p>
<pre><code>[root@git-node1 ~]# git config --global user.name &quot;chenfan&quot;
[root@git-node1 ~]# git config --global user.email &quot;1144102576@qq.com&quot;
[root@git-node1 ~]# git config --global color.ui true
</code></pre><p>1.3 <strong>检查git相关配置</strong></p>
<pre><code>[root@git-node1 ~]# git config --list
user.name=chenfan
user.email=1144102576@qq.com
color.ui=true
</code></pre>
</summary>
<category term="git" scheme="http://www.chenfanlinux.org/categories/git/"/>
<category term="git" scheme="http://www.chenfanlinux.org/tags/git/"/>
</entry>
<entry>
<title>Django基础之模板详解</title>
<link href="http://www.chenfanlinux.org/2018/08/15/Django%E5%9F%BA%E7%A1%80%E4%B9%8B%E6%A8%A1%E6%9D%BF%E8%AF%A6%E8%A7%A3/"/>
<id>http://www.chenfanlinux.org/2018/08/15/Django基础之模板详解/</id>
<published>2018-08-15T10:02:25.000Z</published>
<updated>2019-03-15T15:04:55.000Z</updated>
<content type="html"><![CDATA[<h2 id="创建模板范例"><a href="#创建模板范例" class="headerlink" title="创建模板范例"></a>创建模板范例</h2><blockquote><p>作为Web框架,Django提供了模板,用于编写html代码,还可以嵌入模板代码更快更方便的完成页面开发,再通过在视图中渲染模板,将生成最终的html字符串返回给客户端浏览器。模版致力于表达外观,而不是程序逻辑。模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。</p></blockquote><p>模板包含两部分:</p><ul><li>静态部分,包含html、css、js。</li><li>动态部分,就是模板语言。</li></ul><h3 id="模板简介"><a href="#模板简介" class="headerlink" title="模板简介"></a>模板简介</h3><p>Django模板语言,简写DTL,定义在django.template包中。 创建项目后,在”项目名称/settings.py”文件中定义了关于模板的配置。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRZcKf.png" alt="模板位置"></p><a id="more"></a><p>DIRS定义一个目录列表,模板引擎按列表顺序搜索这些目录以查找模板文件,通常是在项目的根目录下创建templates目录。</p><p>Django处理模板分为两个阶段:</p><ul><li>1.加载:根据给定的路径找到模板文件,编译后放在内存中。</li><li>2.渲染:使用上下文数据对模板插值并返回生成的字符串。</li></ul><p>为了减少开发人员重复编写加载、渲染的代码,Django提供了简写函数render,用于调用模板。</p><h3 id="创建示例项目"><a href="#创建示例项目" class="headerlink" title="创建示例项目"></a>创建示例项目</h3><p>1)创建项目test4。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">django-admin startproject test4</span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/08/15/PRZIGn.png" alt="test4"></p><p>2)进入项目目录test4,创建应用booktest。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> test4</span><br><span class="line">python manage.py startapp booktest</span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/08/15/PRZbrT.png" alt="3"></p><p>3)在test4/settings.py中INSTALLED_APPS项安装应用。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRZjIJ.png" alt="installapp"></p><p>4)在test4/settings.py中DATABASES项配置使用MySQL数据库test2,数据库在第二部分已经创建。</p><p>5)在test4/settings.py中TEMPLATES项配置模板查找路径。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRePsK.png" alt="5"></p><p>6)创建模板目录结构如下。</p><p><img src="https://s1.ax1x.com/2018/08/15/PReYJs.png" alt="6"></p><p>7)打开test4/urls.py文件,包含booktest的url配置。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRedyV.png" alt="7"></p><p>8)在booktest/目录下创建urls.py,配置url。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url</span><br><span class="line"><span class="keyword">from</span> booktest <span class="keyword">import</span> views</span><br><span class="line">urlpatterns=[</span><br><span class="line"> url(<span class="string">r'^$'</span>,views.index),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>9)打开booktest/views.py文件,定义视图index。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> render</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/index.html'</span>)</span><br></pre></td></tr></table></figure><p>10)在templates/booktest目录下创建文件index.html,代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>首页<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>11)打开booktest/models.py文件,定义模型类BookInfo,结构参照第二部分设计。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> btitle = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line"> bpub_date = models.DateField()</span><br><span class="line"> bread = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line"> bcommet = models.IntegerField(default=<span class="number">0</span>)</span><br><span class="line"> isDelete = models.BooleanField(default=<span class="keyword">False</span>)</span><br></pre></td></tr></table></figure><h2 id="模板语言"><a href="#模板语言" class="headerlink" title="模板语言"></a>模板语言</h2><p>模板语言包括4种类型,分别是:</p><ul><li>变量</li><li>标签</li><li>过滤器</li><li>注释</li></ul><h3 id="模板变量"><a href="#模板变量" class="headerlink" title="模板变量"></a>模板变量</h3><p>模板变量的作用是计算并输出,变量名必须由字母、数字、下划线(不能以下划线开头)和点组成。</p><p>语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{{变量}}</span><br></pre></td></tr></table></figure><p>当模版引擎遇到点如book.title,会按照下列顺序解析:</p><ul><li>1.字典book[‘title’]</li><li>2.先属性后方法,将book当作对象,查找属性title,如果没有再查找方法title()</li><li>3.如果是格式为book.0则解析为列表book[0]</li></ul><p>在模板中调用方法时不能传递参数。</p><p><strong>示例</strong></p><p>1)打开booktest/views.py文件,创建视图temp_var。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">temp_var</span><span class="params">(request)</span>:</span></span><br><span class="line"> dict={<span class="string">'title'</span>:<span class="string">'字典键值'</span>}</span><br><span class="line"> book=BookInfo()</span><br><span class="line"> book.btitle=<span class="string">'对象属性'</span></span><br><span class="line"> context={<span class="string">'dict'</span>:dict,<span class="string">'book'</span>:book}</span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/temp_var.html'</span>,context)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^temp_var/$'</span>, views.temp_var),</span><br></pre></td></tr></table></figure><p>3)修改在templates/booktest下创建temp_var.html。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>模板变量<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">模板变量:<span class="tag"><<span class="name">br</span>/></span></span><br><span class="line">{{dict.title}}<span class="tag"><<span class="name">br</span>/></span></span><br><span class="line">{{book.btitl<span class="meta"><!DOCTYPE html></span></span><br><span class="line"><span class="tag"><<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"viewport"</span> <span class="attr">content</span>=<span class="string">"width=device-width, initial-scale=1.0"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">"X-UA-Compatible"</span> <span class="attr">content</span>=<span class="string">"ie=edge"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>模板变量<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">使用字典属性: {{my_dict.title}} <span class="tag"><<span class="name">br</span>></span></span><br><span class="line">使用列表元素: {{my_list.1}} <span class="tag"><<span class="name">br</span>></span></span><br><span class="line">使用对象属性: {{book.btitle}}</span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span>e}}<span class="tag"><<span class="name">br</span>/></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)运行服务器,在浏览器中输入如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/temp_var/</span><br></pre></td></tr></table></figure><h3 id="标签"><a href="#标签" class="headerlink" title="标签"></a>标签</h3><p>语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{%代码段%}</span><br></pre></td></tr></table></figure><p>for标签语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">{%<span class="keyword">for</span> item <span class="keyword">in</span> 列表%}</span><br><span class="line">循环逻辑</span><br><span class="line">{{forloop.counter}}表示当前是第几次循环,从1开始</span><br><span class="line">{%empty%}</span><br><span class="line">列表为空或不存在时执行此逻辑</span><br><span class="line">{%endfor%}</span><br></pre></td></tr></table></figure><p>if标签语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{%<span class="keyword">if</span> ...%}</span><br><span class="line">逻辑1</span><br><span class="line">{%<span class="keyword">elif</span> ...%}</span><br><span class="line">逻辑2</span><br><span class="line">{%<span class="keyword">else</span>%}</span><br><span class="line">逻辑3</span><br><span class="line">{%endif%}</span><br></pre></td></tr></table></figure><p>比较运算符如下:</p><blockquote><p>注意:运算符左右两侧不能紧挨变量或常量,必须有空格。</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">==</span><br><span class="line">!=</span><br><span class="line"><</span><br><span class="line">></span><br><span class="line"><=</span><br><span class="line">>=</span><br></pre></td></tr></table></figure><p>布尔运算符如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">and</span><br><span class="line">or</span><br><span class="line">not</span><br></pre></td></tr></table></figure><p>点击查看<a href="http://python.usyiyi.cn/translate/django_182/ref/templates/builtins.html" target="_blank" rel="noopener">内建标签</a>了解更多标签。</p><p><strong>示例</strong></p><p>1)打开booktest/views.py文件,创建视图temp_tag。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> booktest.models <span class="keyword">import</span> BookInfo</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">temp_tags</span><span class="params">(request)</span>:</span></span><br><span class="line"> context={<span class="string">'list'</span>:BookInfo.objects.all()}</span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/temp_tag.html'</span>,context)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^temp_tag/$'</span>, views.temp_tags),</span><br></pre></td></tr></table></figure><p>3)在templates/booktest下创建temp_tag.html。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>标签<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">图书列表如下:</span><br><span class="line"><span class="tag"><<span class="name">ul</span>></span></span><br><span class="line"> {%for book in list%}</span><br><span class="line"> {%if book.id <span class="tag"><<span class="name">=</span> <span class="attr">2</span>%}</span></span><br><span class="line"> <li style="background-color: red;">{{book.btitle}}</li></span><br><span class="line"> {%elif book.id <span class="tag"><<span class="name">=</span> <span class="attr">3</span>%}</span></span><br><span class="line"> <li style="background-color: blue;">{{book.btitle}}</li></span><br><span class="line"> {%else%}</span><br><span class="line"> <span class="tag"><<span class="name">li</span> <span class="attr">style</span>=<span class="string">"background-color: green;"</span>></span>{{book.btitle}}<span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> {%endif%}</span><br><span class="line"> {%empty%}</span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span>对不起,没有图书<span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> {%endfor%}</span><br><span class="line"><span class="tag"></<span class="name">ul</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)运行服务器,在浏览器中输入如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/temp_tag/</span><br></pre></td></tr></table></figure><p>浏览效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRm16x.png" alt="yunxing"></p><h3 id="过滤器"><a href="#过滤器" class="headerlink" title="过滤器"></a>过滤器</h3><p>语法如下:</p><ul><li>使用管道符号|来应用过滤器,用于进行计算、转换操作,可以使用在变量、标签中。</li><li>如果过滤器需要参数,则使用冒号:传递参数。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">变量|过滤器:参数</span><br></pre></td></tr></table></figure><p>长度length,返回字符串包含字符的个数,或列表、元组、字典的元素个数。</p><p>默认值default,如果变量不存在时则返回默认值。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">data|default:<span class="string">'默认值'</span></span><br></pre></td></tr></table></figure><p>日期date,用于对日期类型的值进行字符串格式化,常用的格式化字符如下:</p><ul><li>Y表示年,格式为4位,y表示两位的年。</li><li>m表示月,格式为01,02,12等。</li><li>d表示日, 格式为01,02等。</li><li>j表示日,格式为1,2等。</li><li>H表示时,24进制,h表示12进制的时。</li><li>i表示分,为0-59。</li><li>s表示秒,为0-59。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">value|date:<span class="string">"Y年m月j日 H时i分s秒"</span></span><br></pre></td></tr></table></figure><p>点击查看<a href="http://python.usyiyi.cn/translate/django_182/ref/templates/builtins.html" target="_blank" rel="noopener">内建过滤器</a>了解更多过滤器。</p><p><strong>示例</strong></p><p>1)打开booktest/views.py文件,创建视图temp_filter。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">temp_filter</span><span class="params">(request)</span>:</span></span><br><span class="line"> context={<span class="string">'list'</span>:BookInfo.objects.all()}</span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/temp_filter.html'</span>,context)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^temp_filter/$'</span>, views.temp_filter),</span><br></pre></td></tr></table></figure><p>3)在templates/booktest下创建temp_filter.html。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>过滤器<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">图书列表如下:</span><br><span class="line"><span class="tag"><<span class="name">ul</span>></span></span><br><span class="line"> {%for book in list%}</span><br><span class="line"> {%if book.btitle|length > 4%}</span><br><span class="line"> <span class="tag"><<span class="name">li</span> <span class="attr">style</span>=<span class="string">"background-color: red;"</span>></span></span><br><span class="line"> {{book.btitle}}</span><br><span class="line"> ---默认时间格式为:</span><br><span class="line"> {{book.bpub_date}}</span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> {%else%}</span><br><span class="line"> <span class="tag"><<span class="name">li</span> <span class="attr">style</span>=<span class="string">"background-color: green;"</span>></span></span><br><span class="line"> {{book.btitle}}</span><br><span class="line"> ---格式化时间为:</span><br><span class="line"> {{book.bpub_date|date:"Y-m-j"}}</span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> {%endif%}</span><br><span class="line"> {%endfor%}</span><br><span class="line"><span class="tag"></<span class="name">ul</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)运行服务器,在浏览器中输入如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/temp_filter/</span><br></pre></td></tr></table></figure><p>浏览效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRmBct.png" alt="过滤器"></p><h3 id="自定义过滤器"><a href="#自定义过滤器" class="headerlink" title="自定义过滤器"></a>自定义过滤器</h3><p>过滤器就是python中的函数,注册后就可以在模板中当作过滤器使用,下面以求余为例开发一个自定义过滤器mod。</p><p><strong>示例</strong></p><p>1)在应用中创建templatetags目录,当前示例为”booktest/templatetags”,创建<em>*init</em>*文件,内容为空。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRm4cq.png" alt="自定义"></p><p>2)在”booktest/templatetags”目录下创建filters.py文件,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#导入Library类</span></span><br><span class="line"><span class="keyword">from</span> django.template <span class="keyword">import</span> Library</span><br><span class="line"></span><br><span class="line"><span class="comment">#创建一个Library类对象</span></span><br><span class="line">register=Library()</span><br><span class="line"></span><br><span class="line"><span class="comment">#使用装饰器进行注册</span></span><br><span class="line"><span class="meta">@register.filter</span></span><br><span class="line"><span class="comment">#定义求余函数mod,将value对2求余</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">mod</span><span class="params">(value)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> value%<span class="number">2</span> == <span class="number">0</span></span><br></pre></td></tr></table></figure><p>3)在templates/booktest/temp_filter.html中,使用自定义过滤器。</p><ul><li>首先使用load标签引入模块。</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{%load filters%}</span><br></pre></td></tr></table></figure><ul><li>在遍历时根据编号判断奇偶,代码改为如下:</li></ul><p><img src="https://s1.ax1x.com/2018/08/15/PRmTBT.png" alt="laod"></p><p>4)运行服务器,浏览效果如下:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRmbEF.md.png" alt="yunxing"></p><p>过滤器可以接收参数,将booktest/templatetags/filters.py中增加mod_num函数。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#使用装饰器进行注册</span></span><br><span class="line"><span class="meta">@register.filter</span></span><br><span class="line"><span class="comment">#定义求余函数mod_num,将value对num求余</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">mod_num</span><span class="params">(value,num)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> value%num</span><br></pre></td></tr></table></figure><p>5)在templates/booktest/temp_filter.html中修改遍历时判断代码。</p><p> <img src="https://s1.ax1x.com/2018/08/15/PRmj3R.png" alt="filter"></p><p>6)运行服务器,浏览效果如下:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRmxjx.png" alt="liulan"></p><h3 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h3><p>在模板中使用如下模板注释,这段代码不会被编译,不会输出到客户端;html注释只能注释html内容,不能注释模板语言。</p><p>1)单行注释语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{<span class="comment">#...#}</span></span><br></pre></td></tr></table></figure><p>注释可以包含任何模版代码,有效的或者无效的都可以。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{<span class="comment"># { % if foo % }bar{ % else % } #}</span></span><br></pre></td></tr></table></figure><p>2)多行注释使用comment标签,语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{%comment%}</span><br><span class="line">...</span><br><span class="line">{%endcomment%}</span><br></pre></td></tr></table></figure><h2 id="模板继承"><a href="#模板继承" class="headerlink" title="模板继承"></a>模板继承</h2><p>模板继承和类的继承含义是一样的,主要是为了提高代码重用,减轻开发人员的工作量。</p><p><strong>典型应用:网站的头部、尾部信息。</strong></p><h3 id="父模板"><a href="#父模板" class="headerlink" title="父模板"></a>父模板</h3><p>如果发现在多个模板中某些内容相同,那就应该把这段内容定义到父模板中。</p><p>标签block:用于在父模板中预留区域,留给子模板填充差异性的内容,名字不能相同。 为了更好的可读性,建议给endblock标签写上名字,这个名字与对应的block名字相同。父模板中也可以使用上下文中传递过来的数据。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{%block 名称%}</span><br><span class="line">预留区域,可以编写默认内容,也可以没有默认内容</span><br><span class="line">{%endblock 名称%}</span><br></pre></td></tr></table></figure><h3 id="子模板"><a href="#子模板" class="headerlink" title="子模板"></a>子模板</h3><p>标签extends:继承,写在子模板文件的第一行。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{% extends <span class="string">"父模板路径"</span>%}</span><br></pre></td></tr></table></figure><p><strong>子模版不用填充父模版中的所有预留区域,如果子模版没有填充,则使用父模版定义的默认值。填充父模板中指定名称的预留区域。</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{%block 名称%}</span><br><span class="line">实际填充内容</span><br><span class="line">{{block.super}}用于获取父模板中block的内容</span><br><span class="line">{%endblock 名称%}</span><br></pre></td></tr></table></figure><h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><p>1)打开booktest/views.py文件,创建视图temp_inherit。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">temp_inherit</span><span class="params">(request)</span>:</span></span><br><span class="line"> context={<span class="string">'title'</span>:<span class="string">'模板继承'</span>,<span class="string">'list'</span>:BookInfo.objects.all()}</span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/temp_inherit.html'</span>,context)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^temp_inherit/$'</span>, views.temp_inherit),</span><br></pre></td></tr></table></figure><p>3)在templates下创建inherit_base.html。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>{{title}}<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"><span class="tag"><<span class="name">h2</span>></span>这是头<span class="tag"></<span class="name">h2</span>></span></span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">{%block qu1%}</span><br><span class="line">这是区域一,有默认值</span><br><span class="line">{%endblock qu1%}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">{%block qu2%}</span><br><span class="line">{%endblock qu2%}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line"><span class="tag"><<span class="name">h2</span>></span>这是尾<span class="tag"></<span class="name">h2</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)在templates/booktest下创建temp_inherit.html。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">{%extends <span class="string">'booktest/inherit_base.html'</span>%}</span><br><span class="line">{%block qu2%}</span><br><span class="line"><ul></span><br><span class="line"> {%<span class="keyword">for</span> book <span class="keyword">in</span> list%}</span><br><span class="line"> <li>{{book.btitle}}</li></span><br><span class="line"> {%endfor%}</span><br><span class="line"></ul></span><br><span class="line">{%endblock qu2%}</span><br></pre></td></tr></table></figure><p>5)运行服务器,在浏览器中输入如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/temp_inherit/</span><br></pre></td></tr></table></figure><p>6)浏览效果如下图。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRu3dO.png" alt="liulan"></p><h2 id="HTML转义"><a href="#HTML转义" class="headerlink" title="HTML转义"></a>HTML转义</h2><h3 id="转义字符"><a href="#转义字符" class="headerlink" title="转义字符"></a>转义字符</h3><p>模板对上下文传递的字符串进行输出时,会对以下字符自动转义。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">小于号< 转换为 &lt;</span><br><span class="line"></span><br><span class="line">大于号> 转换为 &gt;</span><br><span class="line"></span><br><span class="line">单引号<span class="string">' 转换为 &#39;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">双引号" 转换为 &quot;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">与符号& 转换为 &amp;</span></span><br></pre></td></tr></table></figure><h3 id="示例-1"><a href="#示例-1" class="headerlink" title="示例"></a>示例</h3><p>1)打开booktest/views.py文件,创建视图html_escape。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">html_escape</span><span class="params">(request)</span>:</span></span><br><span class="line"> context={<span class="string">'content'</span>:<span class="string">'<h1>hello world</h1>'</span>}</span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/html_escape.html'</span>,context)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^html_escape/$'</span>, views.html_escape),</span><br></pre></td></tr></table></figure><p>3)在templates/booktest/目录下创建html_escape.html。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>转义<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">自动转义:{{content}}</span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)运行服务器,在浏览器中输入如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/html_escape/</span><br></pre></td></tr></table></figure><p>浏览效果如下图:</p><p><img src="file:///I:/itcast2018/03-Django/Django%E6%96%B0%E8%AF%BE%E4%BB%B6/part4/images/p4_1.png" alt="zhuanyi"></p><h3 id="关闭转义"><a href="#关闭转义" class="headerlink" title="关闭转义"></a>关闭转义</h3><p>过滤器escape可以实现对变量的html转义,默认模板就会转义,一般省略。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{{t1|escape}}</span><br></pre></td></tr></table></figure><p>过滤器safe:禁用转义,告诉模板这个变量是安全的,可以解释执行。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{{data|safe}}</span><br></pre></td></tr></table></figure><p>1)修改templates/booktest/html_escape.html代码如下。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>转义<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">自动转义:{{content}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">过滤器safe关闭转义:{{content|safe}}</span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>刷新浏览器后效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRu4mV.png" alt="zhuanyi"></p><p>标签autoescape:设置一段代码都禁用转义,接受on、off参数。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">{%autoescape off%}</span><br><span class="line">...</span><br><span class="line">{%endautoescape%}</span><br></pre></td></tr></table></figure><p>1)修改templates/booktest/html_escape.html代码如下。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>转义<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">自动转义:{{content}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">过滤器safe关闭转义:{{content|safe}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">标签autoescape关闭转义:</span><br><span class="line">{%autoescape off%}</span><br><span class="line">{{content}}</span><br><span class="line">{%endautoescape%}</span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>刷新浏览器后效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRuHfJ.png" alt="guanbizhuanyi"></p><h3 id="字符串字面值"><a href="#字符串字面值" class="headerlink" title="字符串字面值"></a>字符串字面值</h3><p>对于在模板中硬编码的html字符串,不会转义。</p><p>1)修改templates/booktest/html_escape.html代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>转义<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">自动转义:{{content}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">过滤器safe关闭转义:{{content|safe}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">标签autoescape关闭转义:</span><br><span class="line">{%autoescape off%}</span><br><span class="line">{{content}}</span><br><span class="line">{%endautoescape%}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">模板硬编码不转义:{{data|default:'<span class="tag"><<span class="name">b</span>></span>hello<span class="tag"></<span class="name">b</span>></span>'}}</span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>2)刷新浏览器后效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRux0K.png" alt="shuaxin"></p><p>如果希望出现转义的效果,则需要手动编码转义。</p><p>1)修改templates/booktest/html_escape.html代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>转义<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">自动转义:{{content}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">过滤器safe关闭转义:{{content|safe}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">标签autoescape关闭转义:</span><br><span class="line">{%autoescape off%}</span><br><span class="line">{{content}}</span><br><span class="line">{%endautoescape%}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">模板硬编码不转义:{{data|default:'<span class="tag"><<span class="name">b</span>></span>hello<span class="tag"></<span class="name">b</span>></span>'}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">模板硬编码手动转义:{{data|default:"&lt;b&gt;123&lt;/b&gt;"}}</span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>2)刷新浏览器后效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRKpkD.png" alt="shuaxin"></p><h2 id="反向解析"><a href="#反向解析" class="headerlink" title="反向解析"></a>反向解析</h2><h3 id="未使用反向解析"><a href="#未使用反向解析" class="headerlink" title="未使用反向解析"></a>未使用反向解析</h3><p>1) 打开booktest/views.py文件,创建视图fan1、fan2。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fan1</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/fan1.html'</span>)</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fan2</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(<span class="string">'fan2'</span>)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^fan1/$'</span>, views.fan1),</span><br><span class="line">url(r<span class="string">'^fan2/$'</span>, views.fan2),</span><br></pre></td></tr></table></figure><p>3)在templates/booktest/目录下创建fan1.html。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>反向解析<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">普通链接:<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"/fan2/"</span>></span>fan2<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)运行服务器,在浏览器中输入如下网址:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/fan1/</span><br></pre></td></tr></table></figure><p>浏览效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRKnAS.png" alt="fan1"></p><p>5)点击链接后转向fan2,效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRKl1s.png" alt="fan2"></p><p>6)打开booktest/urls.py文件,修改”fan2”的正则表达式为”fan_show”。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^fan_show/$'</span>, views.fan2),</span><br></pre></td></tr></table></figure><p>7)打开浏览器,后退一下,刷新后再次点击链接,浏览如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRKGn0.png" alt="liulanqi"></p><p>问题就来了:随着功能的增加会出现更多的视图,可能之前配置的正则表达式不够准确,于是就要修改正则表达式,但是正则表达式一旦修改了,之前所有对应的超链接都要修改,真是一件麻烦的事情,而且可能还会漏掉一些超链接忘记修改,有办法让链接根据正则表达式动态生成吗? 答:<strong>反向解析</strong>。</p><blockquote><p>反向解析应用在两个地方:模板中的超链接,视图中的重定向。</p></blockquote><h3 id="反向解析-1"><a href="#反向解析-1" class="headerlink" title="反向解析"></a>反向解析</h3><p>要实现反向解析功能,需要如下步骤:</p><p>1)在test4/urls.py中为include定义namespace属性。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^'</span>,include(<span class="string">'booktest.urls'</span>,namespace=<span class="string">'booktest'</span>)),</span><br></pre></td></tr></table></figure><p>2)在booktest/urls.py中为url定义name属性,并修改为fan2。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^fan2/$'</span>, views.fan2,name=<span class="string">'fan2'</span>),</span><br></pre></td></tr></table></figure><p>3)在模板中使用url标签做超链接,此处为templates/booktest/fan1.html文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><html></span><br><span class="line"><head></span><br><span class="line"> <title>反向解析</title></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line">普通链接:<a href="/fan2/">fan2</a></span><br><span class="line"><hr></span><br><span class="line">反向解析:<a href="{%url 'booktest:fan2'%}">fan2</a></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><p>4)回到浏览器中,后退,刷新,查看源文件如下图,两个链接地址一样。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRKsnx.png" alt="4"></p><p>5)在booktest/urls.py中,将fan2修改为fan_show。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^fan_show/$'</span>, views.fan2,name=<span class="string">'fan2'</span>),</span><br></pre></td></tr></table></figure><p>6)回到浏览器中,刷新,查看源文件如下图,两个链接地址不一样。</p><p><img src="https://s1.ax1x.com/2018/08/15/PRK2ND.png" alt="6"></p><p>7)反向解析也可以应用在视图的重定向中。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> redirect</span><br><span class="line"><span class="keyword">from</span> django.core.urlresolvers <span class="keyword">import</span> reverse</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> redirect(reverse(<span class="string">'booktest:fan2'</span>))</span><br></pre></td></tr></table></figure><p>总结:在定义url时,需要为include定义namespace属性,为url定义name属性,使用时,在模板中使用url标签,在视图中使用reverse函数,根据正则表达式动态生成地址,减轻后期维护成本。</p><h3 id="URL的参数"><a href="#URL的参数" class="headerlink" title="URL的参数"></a>URL的参数</h3><p>有些url配置项正则表达式中是有参数的,接下来讲解如何传递参数。</p><h5 id="情况一:位置参数"><a href="#情况一:位置参数" class="headerlink" title="情况一:位置参数"></a>情况一:位置参数</h5><p>1)在booktest/urls.py中,修改fan2如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^fan(\d+)_(\d+)/$'</span>, views.fan3,name=<span class="string">'fan2'</span>),</span><br></pre></td></tr></table></figure><p>2)在booktest/views中,定义视图fan3如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fan3</span><span class="params">(request, a, b)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(a+b)</span><br></pre></td></tr></table></figure><p>3)修改templates/booktest/fan1.html文件如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>反向解析<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">普通链接:<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"/fan2_3/"</span>></span>fan2<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">反向解析:<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"{%url 'booktest:fan2' 2 3%}"</span>></span>fan2<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)回到浏览器中,刷新,查看源文件如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRMDPg.png" alt="chuangcan"></p><p>使用重定向传递位置参数格式如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">return</span> redirect(reverse(<span class="string">'booktest:fan2'</span>, args=(2,3)))</span><br></pre></td></tr></table></figure><h5 id="情况二:关键字参数"><a href="#情况二:关键字参数" class="headerlink" title="情况二:关键字参数"></a>情况二:关键字参数</h5><p>1)在booktest/urls.py中,修改fan2如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^fan(?P<id>\d+)_(?P<age>\d+)/$'</span>, views.fan4,name=<span class="string">'fan2'</span>),</span><br></pre></td></tr></table></figure><p>2)在booktest/views中,定义视图fan4如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fan4</span><span class="params">(request, id, age)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(id+age)</span><br></pre></td></tr></table></figure><p>3)修改templates/booktest/fan1.html文件如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>反向解析<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">普通链接:<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"/fan100_18/"</span>></span>fan2<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"><<span class="name">hr</span>></span></span><br><span class="line">反向解析:<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"{%url 'booktest:fan2' id=100 age=18%}"</span>></span>fan2<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)回到浏览器中,刷新,查看源文件如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/PRM5iF.png" alt="4"></p><p>使用重定向传递关键字参数格式如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">return</span> redirect(reverse(<span class="string">'booktest:fan2'</span>, kwargs={<span class="string">'id'</span>:100,<span class="string">'age'</span>:18}))</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="创建模板范例"><a href="#创建模板范例" class="headerlink" title="创建模板范例"></a>创建模板范例</h2><blockquote>
<p>作为Web框架,Django提供了模板,用于编写html代码,还可以嵌入模板代码更快更方便的完成页面开发,再通过在视图中渲染模板,将生成最终的html字符串返回给客户端浏览器。模版致力于表达外观,而不是程序逻辑。模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。</p>
</blockquote>
<p>模板包含两部分:</p>
<ul>
<li>静态部分,包含html、css、js。</li>
<li>动态部分,就是模板语言。</li>
</ul>
<h3 id="模板简介"><a href="#模板简介" class="headerlink" title="模板简介"></a>模板简介</h3><p>Django模板语言,简写DTL,定义在django.template包中。 创建项目后,在”项目名称/settings.py”文件中定义了关于模板的配置。</p>
<p><img src="https://s1.ax1x.com/2018/08/15/PRZcKf.png" alt="模板位置"></p>
</summary>
<category term="Django入门" scheme="http://www.chenfanlinux.org/categories/Django%E5%85%A5%E9%97%A8/"/>
<category term="Django" scheme="http://www.chenfanlinux.org/tags/Django/"/>
</entry>
<entry>
<title>Django基础之视图详解</title>
<link href="http://www.chenfanlinux.org/2018/08/15/Django%E5%9F%BA%E7%A1%80%E4%B9%8B%E8%A7%86%E5%9B%BE%E8%AF%A6%E8%A7%A3/"/>
<id>http://www.chenfanlinux.org/2018/08/15/Django基础之视图详解/</id>
<published>2018-08-15T02:51:38.000Z</published>
<updated>2018-08-15T02:59:56.000Z</updated>
<content type="html"><![CDATA[<h2 id="视图简单应用"><a href="#视图简单应用" class="headerlink" title="视图简单应用"></a>视图简单应用</h2><h3 id="创建示例项目"><a href="#创建示例项目" class="headerlink" title="创建示例项目"></a>创建示例项目</h3><p>1) 创建项目test3</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> django-admin startproject test3</span></span><br></pre></td></tr></table></figure><p>2) 进入项目目录,创建应用booktest。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">cd</span> test3</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> python manage.py startapp booktest</span></span><br></pre></td></tr></table></figure><p>3) 在test3/settings.py中INSTALLED_APPS项安装应用</p><p><img src="https://s1.ax1x.com/2018/08/14/PgHSrF.png" alt="django_app"></p><p>4) 在test3/settings.py中DATABASES项配置使用MySQL数据库chenfanlinux,数据库在上一篇文章已经创建。</p><p>5) 在test3/settings.py中TEMPLATES项配置模板查找路径。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgHVxK.png" alt="templates"></p><p>6)创建模板目录结构如下。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgHNqg.png" alt="模板目录"></p><a id="more"></a><h3 id="使用视图的过程"><a href="#使用视图的过程" class="headerlink" title="使用视图的过程"></a>使用视图的过程</h3><p>视图就是一个python函数,被定义在”应用/views.py”文件中。 使用视图时需要进行两方面操作,两个操作不分先后。</p><p>1)<strong>在”应用/views.py”中定义视图</strong>。</p><p>在booktest/views.py中定义视图函数index:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(<span class="string">"视图函数index"</span>)</span><br></pre></td></tr></table></figure><p>2)<strong>配置URLconf,将视图函数和url对应起来</strong>。</p><p>在test3/urls.py中编辑加入如下代码:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> include, url</span><br><span class="line"><span class="keyword">from</span> django.contrib <span class="keyword">import</span> admin</span><br><span class="line"></span><br><span class="line">urlpatterns = [</span><br><span class="line"> url(<span class="string">r'^admin/'</span>, include(admin.site.urls)),</span><br><span class="line"> url(<span class="string">r'^'</span>, include(<span class="string">'booktest.urls'</span>)), <span class="comment">#这句代码是新加入的,包含booktest应用中的urls文件</span></span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>在booktest目录下创建urls.py文件并编辑其内容如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url <span class="comment">#导入url函数</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> booktest <span class="keyword">import</span> views <span class="comment">#导入视图模块</span></span><br><span class="line"></span><br><span class="line">urlpatterns = [</span><br><span class="line"> url(<span class="string">r'^$'</span>, views.index), <span class="comment">#建立url和views.index视图函数的关联</span></span><br><span class="line">]</span><br></pre></td></tr></table></figure><h3 id="启动服务器"><a href="#启动服务器" class="headerlink" title="启动服务器"></a>启动服务器</h3><p>启动服务器,并通过浏览器访问 <a href="http://127.0.0.1:8000," target="_blank" rel="noopener">http://127.0.0.1:8000,</a> 页面显示如下:</p><p><img src="https://s1.ax1x.com/2018/08/14/PgHcsU.png" alt="启动服务器"></p><h2 id="URLconf"><a href="#URLconf" class="headerlink" title="URLconf"></a>URLconf</h2><blockquote><p>用户通过在浏览器的地址栏中输入网址请求网站,对于Django开发的网站,由哪一个视图进行处理请求,是由url匹配找到的。</p></blockquote><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><p>1)在test3/settings.py中通过ROOT_URLCONF指定url配置,默认已经有此配置。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgHoz6.png" alt="视图"></p><p>2)打开test3/urls.py可以看到默认配置。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgHLee.png" alt="视图2"></p><p><strong>注意点:</strong></p><ul><li>在test3/urls.py中进行包含配置,在各自应用中创建具体配置。</li><li>定义urlpatterns列表,存储url()对象,这个名称是固定的。</li></ul><h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><p>url()对象,被定义在django.conf.urls包中,有两种语法结构:</p><p><strong>语法一</strong>:包含,一般在自定义应用中创建一个urls.py来定义url。</p><p>这种语法用于test3/urls.py中,目的是将应用的urls配置到应用内部,数据更清晰并且易于维护。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(正则,include(<span class="string">'应用.urls'</span>))</span><br></pre></td></tr></table></figure><p>1)如示例在test3/urls.py文件,包含booktest中的urls。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r'^',include('booktest.urls')),</span><br></pre></td></tr></table></figure><p>2) 如示例在booktest目录下创建urls.py文件。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgbGk9.png" alt="urls"></p><p><strong>语法二</strong>:定义,指定URL和视图函数的对应关系。</p><p>在应用内部创建urls.py文件,指定请求地址与视图的对应关系。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(正则,<span class="string">'视图函数名称'</span>)</span><br></pre></td></tr></table></figure><p>1)如示例在booktest/urls.py中创建首页的url,代码如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url</span><br><span class="line"><span class="keyword">from</span> booktest <span class="keyword">import</span> views</span><br><span class="line">urlpatterns=[</span><br><span class="line"> url(<span class="string">r'^$'</span>,views.index),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>2)如示例在booktest/views.py中创建视图index</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> render</span><br><span class="line"><span class="keyword">from</span> django.http <span class="keyword">import</span> HttpResponse</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(<span class="string">"视图函数index"</span>)</span><br></pre></td></tr></table></figure><blockquote><p>说明1:正则部分推荐使用r,表示字符串不转义,这样在正则表达式中使用\只写一个就可以。</p><p> 说明2:不能在开始加反斜杠,推荐在结束加反斜杠。</p></blockquote><h3 id="获取值"><a href="#获取值" class="headerlink" title="获取值"></a>获取值</h3><p>请求的url被看做是一个普通的python字符串,进行匹配时不包括域名、get或post参数。 如请求地址如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/delete1/?a=10</span><br></pre></td></tr></table></figure><p>1)去除掉域名和参数部分,并将最前面的/去除后,只剩下如下部分与正则匹配。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">delete1/</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,定义与这个地址匹配的url如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^delete\d+/$'</span>,views.show_arg),</span><br></pre></td></tr></table></figure><p>3)在booktest/views.py中创建视图show_arg。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">show_arg</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(<span class="string">'show_arg'</span>)</span><br></pre></td></tr></table></figure><p>4)启动服务器,输入上面的网址,浏览器中效果如下图。</p><p><img src="https://s1.ax1x.com/2018/08/14/Pgbskd.png" alt="qidongfuwuqi"></p><p>可以在匹配过程中从url中捕获参数,每个捕获的参数都作为一个普通的python字符串传递给视图。</p><p>获取值需要在正则表达式中使用小括号,分为两种方式:</p><ul><li>位置参数</li><li>关键字参数</li></ul><blockquote><p>注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式。</p></blockquote><p><strong>方式一:位置参数</strong></p><p>直接使用小括号,通过位置参数传递给视图。</p><p>1)为了提取参数,修改上面的正则表达式如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^delete(\d+)/$'</span>,views.show_arg),</span><br></pre></td></tr></table></figure><p>2)修改视图show_arg如下:</p><blockquote><p>注意:参数的名字是任意的如a1、b8,尽量做到见名知意。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">def show_arg(request,id):</span><br><span class="line"> return HttpResponse('show arg %s'%id)</span><br></pre></td></tr></table></figure><p>3)刷新浏览器页面,效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/Pgb6fI.png" alt="show_arg1"></p><p> 4)在地址栏输入如下地址:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/2/?a=10</span><br></pre></td></tr></table></figure><p>5)浏览器页面效果如下图</p><p><img src="https://s1.ax1x.com/2018/08/14/PgbR6f.png" alt="arg2"></p><p><strong>方式二:关键字参数</strong></p><p>在正则表达式部分为组命名。</p><p>1)修改正则表达式如下:</p><blockquote><p>其中?P部分表示为这个参数定义的名称为id,可以是其它名称,起名做到见名知意。</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^delete(?P<id1>\d+)/$'</span>,views.show_arg),</span><br></pre></td></tr></table></figure><p>2)修改视图show_arg如下:</p><blockquote><p>注意:视图show_arg此时必须要有一个参数名为id1,否则报错。</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">show_arg</span><span class="params">(request,id1)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(<span class="string">'show %s'</span>%id1)</span><br></pre></td></tr></table></figure><p>3)刷新浏览器页面,效果如下图</p><p><img src="https://s1.ax1x.com/2018/08/14/Pgbokj.png" alt="argsid"></p><h2 id="视图"><a href="#视图" class="headerlink" title="视图"></a>视图</h2><blockquote><p>视图就是python中的函数,视图一般被定义在”应用/views.py”文件中,此例中为”booktest/views.py”文件。视图必须返回一个HttpResponse对象或子对象作为响应。响应可以是一张网页的HTML内容,一个重定向,一个404错误等。</p></blockquote><p>视图的第一个参数必须为HttpRequest实例,还可能包含下参数如:</p><ul><li>通过正则表达式组获得的关键字参数。</li><li>通过正则表达式组获取的位置参数。</li></ul><p>Django内置处理HTTP错误的视图,主要错误及视图包括:</p><ul><li>404错误:page not found视图</li><li>500错误:server error视图</li></ul><p>如果想看到错误视图而不是调试信息,需要修改test3/setting.py文件的DEBUG项。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">DEBUG = False</span><br><span class="line">ALLOWED_HOSTS = [<span class="string">'*'</span>, ] <span class="comment"># 允许所有主机</span></span><br></pre></td></tr></table></figure><h3 id="404错误及视图"><a href="#404错误及视图" class="headerlink" title="404错误及视图"></a>404错误及视图</h3><blockquote><p>将请求地址进行url匹配后,没有找到匹配的正则表达式,则调用404视图,这个视图会调用404.html的模板进行渲染。视图传递变量request_path给模板,表示导致错误的URL。</p></blockquote><p>1)在templates中创建404.html。</p><p><img src="https://s1.ax1x.com/2018/08/14/Pgb7hn.png" alt="404"></p><p>2)定义代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span><span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">找不到了</span><br><span class="line"><span class="tag"><<span class="name">hr</span>/></span></span><br><span class="line">{{request_path}}</span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>3)在浏览器中输入如下网址:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/<span class="built_in">test</span>/</span><br></pre></td></tr></table></figure><p>4)运行效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/PgbLcV.png" alt="404page"></p><h3 id="500错误及视图"><a href="#500错误及视图" class="headerlink" title="500错误及视图"></a>500错误及视图</h3><p>在视图中代码运行报错会发生500错误,调用内置错误视图,使用templates/500.html模板渲染。</p><p>视图处理过程如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/PgbOXT.png" alt="505"></p><h2 id="HttpReqeust对象"><a href="#HttpReqeust对象" class="headerlink" title="HttpReqeust对象"></a>HttpReqeust对象</h2><blockquote><p>服务器接收到http协议的请求后,会根据报文创建HttpRequest对象,这个对象不需要我们创建,直接使用服务器构造好的对象就可以。<strong>视图的第一个参数必须是HttpRequest对象</strong>,在django.http模块中定义了HttpRequest对象的API。</p></blockquote><h3 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h3><ul><li>path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。</li><li>method:一个字符串,表示请求使用的HTTP方法,常用值包括:’GET’、’POST’。<ul><li>在浏览器中给出地址发出请求采用get方式,如超链接。</li><li>在浏览器中点击表单的提交按钮发起请求,如果表单的method设置为post则为post请求。</li></ul></li><li>encoding:一个字符串,表示提交的数据的编码方式。<ul><li>如果为None则表示使用浏览器的默认设置,一般为utf-8。</li><li>这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值。</li></ul></li><li>GET:QueryDict类型对象,类似于字典,包含get请求方式的所有参数。</li><li>POST:QueryDict类型对象,类似于字典,包含post请求方式的所有参数。</li><li>FILES:一个类似于字典的对象,包含所有的上传文件。</li><li>COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串。</li><li>session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用,详细内容见”状态保持”。</li></ul><h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><p><strong>path</strong></p><p>1)打开booktest/views.py文件,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> str=<span class="string">'%s,%s'</span>%(request.path,request.encoding)</span><br><span class="line"> <span class="keyword">return</span> render(request, <span class="string">'booktest/index.html'</span>, {<span class="string">'str'</span>:str})</span><br></pre></td></tr></table></figure><p>2)在templates/booktest/下创建index.html文件,代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>首页<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">1. request对象的path,encoding属性:<span class="tag"><<span class="name">br</span>/></span></span><br><span class="line">{{ str }}</span><br><span class="line"><span class="tag"><<span class="name">br</span>/></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>3)打开浏览器请求,运行效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/PgqnNd.png" alt="liulanqi"></p><p>4)以chrome浏览器为例,设置编码如下图,默认为utf-8编码</p><p><strong>method</strong></p><p>1)打开booktest/views.py文件,编写视图method_show,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">method_show</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(request.method)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,新增配置如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^method_show/$'</span>, views.method_show),</span><br></pre></td></tr></table></figure><p>3)修改templates/booktest/下创建index.html文件,添加代码如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><html></span><br><span class="line"><head></span><br><span class="line"> <title>首页</title></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line">...</span><br><span class="line">...</span><br><span class="line">2.request对象的method属性:<br/></span><br><span class="line"><a href=<span class="string">'/method_show/'</span>>get方式</a><br/></span><br><span class="line"><form method=<span class="string">"post"</span> action=<span class="string">"/method_show/"</span>></span><br><span class="line"> <input <span class="built_in">type</span>=<span class="string">"submit"</span> value=<span class="string">"post方式"</span>></span><br><span class="line"></form></span><br><span class="line"><br/></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><p>4)打开浏览器,输入如下网址:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/</span><br></pre></td></tr></table></figure><p>5)浏览效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/Pgq1jf.png" alt="shouye"></p><p>6)点击链接,转到method_show,浏览效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/PgqNNj.png" alt="get"></p><p>7) 回到method_test页面,点击按钮,转到method_post,浏览效果如下图,报错了。</p><p><img src="https://s1.ax1x.com/2018/08/14/Pgqw3q.png" alt="method_test"></p><p>8)打开test3/settings.py文件,将MIDDLEWARE_CLASSES项的csrf注释。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgqBvV.png" alt="6"></p><p>9)回到浏览器中刷新,浏览效果如下图,点击“继续”按钮。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgqybF.png" alt="9"></p><p>10)最终浏览效果如下图</p><p><img src="https://s1.ax1x.com/2018/08/14/PgqgUJ.png" alt="10"></p><h2 id="HttpResponse对象"><a href="#HttpResponse对象" class="headerlink" title="HttpResponse对象"></a>HttpResponse对象</h2><blockquote><p>视图在接收请求并处理后,必须返回HttpResponse对象或子对象。在django.http模块中定义了HttpResponse对象的API。HttpRequest对象由Django创建,HttpResponse对象由开发人员创建。</p></blockquote><h3 id="属性和方法"><a href="#属性和方法" class="headerlink" title="属性和方法"></a>属性和方法</h3><p><strong>属性</strong></p><ul><li>content:表示返回的内容。</li><li>charset:表示response采用的编码字符集,默认为utf-8。</li><li>status_code:返回的HTTP响应状态码。</li><li>content-type:指定返回数据的的MIME类型,默认为’text/html’。</li></ul><p><strong>方法</strong></p><ul><li><em>*init</em>*:创建HttpResponse对象后完成返回内容的初始化。</li><li>set_cookie:设置Cookie信息。 set_cookie(key, value=’’, max_age=None, expires=None)</li><li>cookie是网站以键值对格式存储在浏览器中的一段纯文本信息,用于实现用户跟踪。<ul><li>max_age是一个整数,表示在指定秒数后过期。</li><li>expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期。</li><li>max_age与expires二选一。</li><li>如果不指定过期时间,在关闭浏览器时cookie会过期。</li></ul></li><li>delete_cookie(key):删除指定的key的Cookie,如果key不存在则什么也不发生。</li><li>write:向响应体中写数据。</li></ul><h3 id="示例-1"><a href="#示例-1" class="headerlink" title="示例"></a>示例</h3><h4 id="直接返回数据"><a href="#直接返回数据" class="headerlink" title="直接返回数据"></a>直接返回数据</h4><p>1)打开booktest/views.py文件,定义视图index2如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index2</span><span class="params">(request)</span>:</span></span><br><span class="line"> str=<span class="string">'<h1>hello world</h1>'</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(str)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^index2/$'</span>,views.index2),</span><br></pre></td></tr></table></figure><p>3)运行服务器,在浏览器中打开如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/index2/</span><br></pre></td></tr></table></figure><p>运行效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/Pgqq5d.png" alt="直接返回数据"></p><p><strong>如果使用这种方式构造一个漂亮丰富的页面,对于开发人员真是会发疯,于是就有了下面的方式:</strong></p><h4 id="调用模板"><a href="#调用模板" class="headerlink" title="调用模板"></a>调用模板</h4><p>可以将html、css、js定义到一个html文件中,然后由视图来调用。</p><p>1)打开booktest/views.py文件,定义视图index3如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.template <span class="keyword">import</span> RequestContext, loader</span><br><span class="line">...</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index3</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="comment">#加载模板</span></span><br><span class="line"> t1=loader.get_template(<span class="string">'booktest/index3.html'</span>)</span><br><span class="line"> <span class="comment">#构造上下文</span></span><br><span class="line"> context=RequestContext(request,{<span class="string">'h1'</span>:<span class="string">'hello'</span>})</span><br><span class="line"> <span class="comment">#使用上下文渲染模板,生成字符串后返回响应对象</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(t1.render(context))</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^index3/$'</span>,views.index3),</span><br></pre></td></tr></table></figure><p>3)在templates/booktest/目录下创建index3.html,代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>使用模板<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"><span class="tag"><<span class="name">h1</span>></span>{{h1}}<span class="tag"></<span class="name">h1</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>4)运行服务器,在浏览器中打开如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/index3/</span><br></pre></td></tr></table></figure><p>运行效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/14/PgqOPA.png" alt="4"></p><h4 id="调用模板简写函数render"><a href="#调用模板简写函数render" class="headerlink" title="调用模板简写函数render"></a>调用模板简写函数render</h4><p>每次调用模板时都要执行加载、上下文、渲染三个步骤,为了简化操作,Django定义了render()函数封装了以上三个步骤的代码,定义在django.shortcuts模块中。</p><p>1)打开booktest/views.py文件,定义视图index3如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> render</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index3</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> render(request, <span class="string">'booktest/index3.html'</span>, {<span class="string">'h1'</span>: <span class="string">'hello'</span>})</span><br></pre></td></tr></table></figure><p><strong>是不是用render()函数调用模板比上面简单多了?</strong></p><h3 id="子类JsonResponse"><a href="#子类JsonResponse" class="headerlink" title="子类JsonResponse"></a>子类JsonResponse</h3><blockquote><p>在浏览器中使用javascript发起ajax请求时,返回json格式的数据,此处以jquery的get()方法为例。类JsonResponse继承自HttpResponse对象,被定义在django.http模块中,创建对象时接收字典作为参数。</p></blockquote><p><strong>示例</strong></p><p>1)在booktest/views.py文件中定义视图json1、json2,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.http <span class="keyword">import</span> JsonResponse</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">json1</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/json1.html'</span>)</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">json2</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> JsonResponse({<span class="string">'h1'</span>:<span class="string">'hello'</span>,<span class="string">'h2'</span>:<span class="string">'world'</span>})</span><br></pre></td></tr></table></figure><p>2)在booktest/urls.py文件中配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^json1/$'</span>, views.json1),</span><br><span class="line">url(r<span class="string">'^json2/$'</span>, views.json2),</span><br></pre></td></tr></table></figure><p>3)创建目录static/js/,把jquery文件拷贝到这个目录下。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgLKZF.png" alt="jquery"></p><p>4)打开test3/settings.py文件,在文件最底部,配置静态文件查找路径,并且要求开启调试</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">DEBUG = True</span><br><span class="line">...</span><br><span class="line">STATICFILES_DIRS = [</span><br><span class="line"> os.path.join(BASE_DIR, <span class="string">'static'</span>),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>5)在templates/booktest/目录下创建json1.html,代码如下:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>json<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"/static/js/jquery-1.12.4.min.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"> $(function () {</span></span><br><span class="line"><span class="undefined"> $('#btnJson').click(function () {</span></span><br><span class="line"><span class="undefined"> $.get('/json2/',function (data) {</span></span><br><span class="line"><span class="undefined"> ul=$('#jsonList');</span></span><br><span class="line"><span class="xml"> ul.append('<span class="tag"><<span class="name">li</span>></span>'+data['h1']+'<span class="tag"></<span class="name">li</span>></span>')</span></span><br><span class="line"><span class="xml"> ul.append('<span class="tag"><<span class="name">li</span>></span>'+data['h2']+'<span class="tag"></<span class="name">li</span>></span>')</span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="undefined"> });</span></span><br><span class="line"><span class="undefined"> });</span></span><br><span class="line"><span class="undefined"> </span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">id</span>=<span class="string">"btnJson"</span> <span class="attr">value</span>=<span class="string">"获取json数据"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">ul</span> <span class="attr">id</span>=<span class="string">"jsonList"</span>></span><span class="tag"></<span class="name">ul</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>6)运行服务器,在浏览器中输入如下地址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/json1/</span><br></pre></td></tr></table></figure><p>7)点击按钮”获取json数据”后浏览如下图。</p><p><img src="https://s1.ax1x.com/2018/08/14/PgLQIJ.png" alt="json"></p><p>ajax代码执行过程如下:</p><ul><li>1.发起请求。</li><li>2.服务器端视图函数执行。</li><li>3.执行回调函数。</li></ul><p><img src="https://s1.ax1x.com/2018/08/14/PgLReS.png" alt="jsonresponse"></p><h2 id="状态保持"><a href="#状态保持" class="headerlink" title="状态保持"></a>状态保持</h2><blockquote><p>浏览器请求服务器是无状态的。无状态指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。无状态的应用层面的原因是:浏览器和服务器之间的通信都遵守HTTP协议。根本原因是:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。</p></blockquote><p>有时需要保存下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等。 实现状态保持主要有两种方式:</p><ul><li>在客户端存储信息使用Cookie。</li><li>在服务器端存储信息使用Session。</li></ul><h3 id="Cookie"><a href="#Cookie" class="headerlink" title="Cookie"></a>Cookie</h3><blockquote><p>Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否是合法用户以及是否需要重新登录等。服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。Cookies最典型记住用户名。</p></blockquote><h4 id="Cookie的特点"><a href="#Cookie的特点" class="headerlink" title="Cookie的特点"></a>Cookie的特点</h4><ul><li>Cookie以键值对的格式进行信息的存储。</li><li>Cookie基于域名安全,不同域名的Cookie是不能互相访问的,如访问itcast.cn时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到itcast.cn写的Cookie信息。</li><li>当浏览器请求某网站时,会将浏览器存储的跟网站相关的所有Cookie信息提交给网站服务器。</li></ul><h4 id="设置Cookie"><a href="#设置Cookie" class="headerlink" title="设置Cookie"></a>设置Cookie</h4><p>1)打开booktest/views.py文件,创建视图cookie_set。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># cookie可以设置到HttpResponse类及其子类对象中</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">cookie_set</span><span class="params">(request)</span>:</span></span><br><span class="line"> response = HttpResponse(<span class="string">"<h1>设置Cookie,请查看响应报文头</h1>"</span>)</span><br><span class="line"> response.set_cookie(<span class="string">'h1'</span>, <span class="string">'你好'</span>)</span><br><span class="line"> <span class="keyword">return</span> response</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^cookie_set/$'</span>,views.cookie_set),</span><br></pre></td></tr></table></figure><p>3)在浏览器输入如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/cookie_set/</span><br></pre></td></tr></table></figure><p>在”开发者工具”中可以在响应头中查看到设置的Cookie信息。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2OgxI.png" alt="设置cookie"></p><h4 id="读取Cookie"><a href="#读取Cookie" class="headerlink" title="读取Cookie"></a>读取Cookie</h4><p>Cookie信息被包含在请求头中,使用request对象的COOKIES属性访问。</p><p>1)打开booktest/views.py文件,创建视图cookie_get。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">cookie_get</span><span class="params">(request)</span>:</span></span><br><span class="line"> response = HttpResponse(<span class="string">"读取Cookie,数据如下:<br>"</span>)</span><br><span class="line"> <span class="keyword">if</span> <span class="string">'h1'</span> <span class="keyword">in</span> request.COOKIES:</span><br><span class="line"> response.write(<span class="string">'<h1>'</span> + request.COOKIES[<span class="string">'h1'</span>] + <span class="string">'</h1>'</span>)</span><br><span class="line"> <span class="keyword">return</span> response</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^cookie_get/$'</span>,views.cookie_get),</span><br></pre></td></tr></table></figure><p>3)在浏览器输入如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/cookie_get/</span><br></pre></td></tr></table></figure><p>4)打开“开发者工具”,在请求头中可以查看Cookie信息,浏览效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/15/P2O5dS.png" alt="设置cookie"></p><h3 id="Session"><a href="#Session" class="headerlink" title="Session"></a>Session</h3><p>对于敏感、重要的信息,建议要储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息。</p><blockquote><p>在服务器端进行状态保持的方案就是Session。</p></blockquote><h4 id="启用Session"><a href="#启用Session" class="headerlink" title="启用Session"></a>启用Session</h4><p>Django项目默认启用Session。</p><p>打开test3/settings.py文件,在项MIDDLEWARE_CLASSES中启用Session中间件。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2OLMq.md.png" alt="qiyongsession"></p><h4 id="存储方式"><a href="#存储方式" class="headerlink" title="存储方式"></a>存储方式</h4><p>打开test3/settings.py文件,设置SESSION_ENGINE项指定Session数据存储的方式,可以存储在数据库、缓存、Redis等。</p><p>1)存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SESSION_ENGINE=<span class="string">'django.contrib.sessions.backends.db'</span></span><br></pre></td></tr></table></figure><p>2)存储在缓存中:存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SESSION_ENGINE=<span class="string">'django.contrib.sessions.backends.cache'</span></span><br></pre></td></tr></table></figure><p>3)混合存储:优先从本机内存中存取,如果没有则从数据库中存取。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SESSION_ENGINE=<span class="string">'django.contrib.sessions.backends.cached_db'</span></span><br></pre></td></tr></table></figure><p>4)如果存储在数据库中,需要在项INSTALLED_APPS中安装Session应用。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2XPzR.png" alt="session"></p><p>5)迁移后会在数据库中创建出存储Session的表。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2XFQ1.png" alt="session"></p><p>6)表结构如下图。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2XAL6.png" alt="biaojiegou"></p><blockquote><p>由表结构可知,操作Session包括三个数据:键,值,过期时间</p></blockquote><h4 id="依赖于Cookie"><a href="#依赖于Cookie" class="headerlink" title="依赖于Cookie"></a>依赖于Cookie</h4><p>所有请求者的Session都会存储在服务器中,服务器如何区分请求者和Session数据的对应关系呢?</p><p>答:在使用Session后,会在Cookie中存储一个sessionid的数据,每次请求时浏览器都会将这个数据发给服务器,服务器在接收到sessionid后,会根据这个值找出这个请求者的Session。</p><p>结果:如果想使用Session,浏览器必须支持Cookie,否则就无法使用Session了。</p><p>存储Session时,键与Cookie中的sessionid相同,值是开发人员设置的键值对信息,进行了base64编码,过期时间由开发人员设置。</p><h4 id="对象及方法"><a href="#对象及方法" class="headerlink" title="对象及方法"></a>对象及方法</h4><p>通过HttpRequest对象的session属性进行会话的读写操作</p><p>1) 以键值对的格式写session。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">request.session[<span class="string">'键'</span>]=值</span><br></pre></td></tr></table></figure><p>2)根据键读取值。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">request.session.get(<span class="string">'键'</span>,默认值)</span><br></pre></td></tr></table></figure><p>3)清除所有session,在存储中删除值部分。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">request.session.clear()</span><br></pre></td></tr></table></figure><p>4)清除session数据,在存储中删除session的整条数据。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">request.session.flush()</span><br></pre></td></tr></table></figure><p>5)删除session中的指定键及值,在存储中只删除某个键及对应的值。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">del request.session[<span class="string">'键'</span>]</span><br></pre></td></tr></table></figure><p>6)设置会话的超时时间,如果没有指定过期时间则两个星期后过期。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">request.session.set_expiry(value)</span><br></pre></td></tr></table></figure><ul><li>如果value是一个整数,会话将在value秒没有活动后过期。</li><li>如果value为0,那么用户会话的Cookie将在用户的浏览器关闭时过期。</li><li>如果value为None,那么会话永不过期。</li></ul><h4 id="示例-2"><a href="#示例-2" class="headerlink" title="示例"></a>示例</h4><p><strong>写session </strong></p><p>1)打开booktest/views.py文件,创建视图session_test,代码如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">def session_test(request):</span><br><span class="line"> request.session[<span class="string">'h1'</span>]=<span class="string">'hello'</span></span><br><span class="line"> <span class="built_in">return</span> HttpResponse(<span class="string">'写session'</span>)</span><br></pre></td></tr></table></figure><p>2)打开booktest/urls.py文件,配置url。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(r<span class="string">'^session_test/$'</span>,views.session_test),</span><br></pre></td></tr></table></figure><p>3)运行服务器,打开浏览器请求如下网址。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/session_test/</span><br></pre></td></tr></table></figure><p>4)浏览效果如下图,在”开发者工具”中可以查看到响应头中创建了Cookie,里面有个键为sessionid。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2XYTS.png" alt="session"></p><p>5)打开MySQL数据库命令行,查询数据如下图。</p><p>查看Cookie中的sessionid值为”l48euizwnd0u1vrq401rwc9yqxkj4ip4”,数据表中session的键为“l48euizwnd0u1vrq401rwc9yqxkj4ip4”,是一样的,这样,服务器就可以在众多的请求者中找到对应的Session数据。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2XwSs.png" alt="mysql"></p><p><strong>读session </strong></p><p>1)打开booktest/views.py文件,修改session_test视图如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">session_test</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="comment"># request.session['h1']='hello'</span></span><br><span class="line"> h1=request.session.get(<span class="string">'h1'</span>)</span><br><span class="line"> <span class="keyword">return</span> HttpResponse(h1)</span><br></pre></td></tr></table></figure><p>2)刷新浏览器效果如下图。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2XByq.png" alt="shuaxin"></p><h4 id="使用Redis存储Session"><a href="#使用Redis存储Session" class="headerlink" title="使用Redis存储Session"></a>使用Redis存储Session</h4><p>会话还支持文件、纯cookie、Memcached、Redis等方式存储,下面演示使用redis存储。</p><p>1)安装包。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install django-redis-sessions==<span class="number">0.5</span><span class="number">.6</span></span><br></pre></td></tr></table></figure><p>2)修改test3/settings文件,增加如下项:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">SESSION_ENGINE = <span class="string">'redis_sessions.session'</span></span><br><span class="line">SESSION_REDIS_HOST = <span class="string">'localhost'</span></span><br><span class="line">SESSION_REDIS_PORT = 6379</span><br><span class="line">SESSION_REDIS_DB = 2</span><br><span class="line">SESSION_REDIS_PASSWORD = <span class="string">''</span></span><br><span class="line">SESSION_REDIS_PREFIX = <span class="string">'session'</span></span><br></pre></td></tr></table></figure><p>3)打开booktest/views.py文件,修改session_test视图如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">session_test</span><span class="params">(request)</span>:</span></span><br><span class="line"> request.session[<span class="string">'h1'</span>]=<span class="string">'hello'</span></span><br><span class="line"> <span class="comment"># h1=request.session.get('h1')</span></span><br><span class="line"> <span class="comment"># del request.session['h1']</span></span><br><span class="line"> <span class="comment"># request.session.flush()</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(<span class="string">'ok'</span>)</span><br></pre></td></tr></table></figure><p>4)管理redis的命令,需要保证redis服务被开启。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">查看:ps ajx|grep redis</span><br><span class="line">启动:sudo service redis start</span><br><span class="line">停止:sudo service redis stop</span><br><span class="line">使用客户端连接服务器:redis-cli</span><br><span class="line">切换数据库:select <span class="number">2</span></span><br><span class="line">查看所有的键:keys *</span><br><span class="line">获取指定键的值:get name</span><br></pre></td></tr></table></figure><p>5)刷新浏览器,在redis客户端中查看数据如下。</p><p><img src="https://s1.ax1x.com/2018/08/15/P2XXpd.png" alt="redis"></p>]]></content>
<summary type="html">
<h2 id="视图简单应用"><a href="#视图简单应用" class="headerlink" title="视图简单应用"></a>视图简单应用</h2><h3 id="创建示例项目"><a href="#创建示例项目" class="headerlink" title="创建示例项目"></a>创建示例项目</h3><p>1) 创建项目test3</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> django-admin startproject test3</span></span><br></pre></td></tr></table></figure>
<p>2) 进入项目目录,创建应用booktest。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">cd</span> test3</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> python manage.py startapp booktest</span></span><br></pre></td></tr></table></figure>
<p>3) 在test3/settings.py中INSTALLED_APPS项安装应用</p>
<p><img src="https://s1.ax1x.com/2018/08/14/PgHSrF.png" alt="django_app"></p>
<p>4) 在test3/settings.py中DATABASES项配置使用MySQL数据库chenfanlinux,数据库在上一篇文章已经创建。</p>
<p>5) 在test3/settings.py中TEMPLATES项配置模板查找路径。</p>
<p><img src="https://s1.ax1x.com/2018/08/14/PgHVxK.png" alt="templates"></p>
<p>6)创建模板目录结构如下。</p>
<p><img src="https://s1.ax1x.com/2018/08/14/PgHNqg.png" alt="模板目录"></p>
</summary>
<category term="Django入门" scheme="http://www.chenfanlinux.org/categories/Django%E5%85%A5%E9%97%A8/"/>
<category term="Django" scheme="http://www.chenfanlinux.org/tags/Django/"/>
</entry>
<entry>
<title>Django入门基础之模型</title>
<link href="http://www.chenfanlinux.org/2018/08/13/Django%E5%85%A5%E9%97%A8%E5%9F%BA%E7%A1%80%E4%B9%8B%E6%A8%A1%E5%9E%8B/"/>
<id>http://www.chenfanlinux.org/2018/08/13/Django入门基础之模型/</id>
<published>2018-08-13T04:16:56.000Z</published>
<updated>2018-08-13T04:18:17.000Z</updated>
<content type="html"><![CDATA[<h2 id="ORM简介"><a href="#ORM简介" class="headerlink" title="ORM简介"></a>ORM简介</h2><blockquote><p>ORM,全拼Object-Relation Mapping,中文意为对象-关系映射,是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射ORM系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。O/R中字母O起源于”对象”(Object),而R则来自于”关系”(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。</p></blockquote><h3 id="ORM的好处"><a href="#ORM的好处" class="headerlink" title="ORM的好处"></a>ORM的好处</h3><p>在MVC框架中的Model模块中都包括ORM,对于开发人员主要带来了如下好处:</p><ul><li>实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码。</li><li>只需要面向对象编程,不需要面向数据库编写代码。</li><li>在MVC中Model中定义的类,通过ORM与关系型数据库中的表对应,对象的属性体现对象间的关系,这种关系也被映射到数据表中。</li></ul><h3 id="ORM示意图"><a href="#ORM示意图" class="headerlink" title="ORM示意图"></a>ORM示意图</h3><p><img src="https://s1.ax1x.com/2018/08/13/Pgp8yR.png" alt="ORM示意图"></p><a id="more"></a><h3 id="更换数据库为MySQL"><a href="#更换数据库为MySQL" class="headerlink" title="更换数据库为MySQL"></a>更换数据库为MySQL</h3><p><strong>创建一个新的的项目test</strong></p><p>进入虚拟环境py_django。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> workon py_django</span></span><br></pre></td></tr></table></figure><p>在/home/python/pytest目录下创建项目test2。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> django-admin startproject test2</span></span><br></pre></td></tr></table></figure><p>下面是手动创建数据库,打开新终端,在命令行登录mysql,创建数据库test2。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">mysql></span><span class="bash"> create database chenfanlinux charset=utf8;</span></span><br></pre></td></tr></table></figure><p>打开test2/settings.py文件,找到DATABASES项,默认使用SQLite3数据库</p><p><img src="https://s1.ax1x.com/2018/08/13/PgpgTf.png" alt="sqlite"></p><p>修改为使用MySQL数据库,代码如下:</p><blockquote><p>将引擎改为mysql,提供连接的主机HOST、端口PORT、数据库名NAME、用户名USER、密码PASSWORD。</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">DATABASES = {</span><br><span class="line"> 'default': {</span><br><span class="line"> 'ENGINE': 'django.db.backends.mysql',</span><br><span class="line"> 'NAME': 'chenfanlinux', #数据库名字,</span><br><span class="line"> 'USER': 'root', #数据库登录用户名</span><br><span class="line"> 'PASSWORD': 'mysql', #数据库登录密码</span><br><span class="line"> 'HOST': 'localhost', #数据库所在主机</span><br><span class="line"> 'PORT': '3306', #数据库端口</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>返回第一个终端,进入test2目录,创建应用booktest。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">cd</span> test2</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> python manage.py startapp booktest</span></span><br></pre></td></tr></table></figure><p>将应用booktest注册到项目中:打开test2/settings.py文件,找到INSTALLED_APPS项,加入如下代码:</p><p><img src="https://s1.ax1x.com/2018/08/13/Pgp7mq.png" alt="booktest"></p><h2 id="实例演示"><a href="#实例演示" class="headerlink" title="实例演示"></a>实例演示</h2><ul><li>模型类被定义在”应用/models.py”文件中,此例中为”booktest/models.py”文件。</li><li>模型类必须继承自Model类,位于包django.db.models中。</li><li>提示:对于重要数据使用逻辑删除。</li></ul><h3 id="定义模型类"><a href="#定义模型类" class="headerlink" title="定义模型类"></a>定义模型类</h3><p><strong>1.打开booktest/models.py文件,定义模型类如下</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="comment">#定义图书模型类BookInfo</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> btitle = models.CharField(max_length=<span class="number">20</span>)<span class="comment">#图书名称</span></span><br><span class="line"> bpub_date = models.DateField()<span class="comment">#发布日期</span></span><br><span class="line"> bread = models.IntegerField(default=<span class="number">0</span>)<span class="comment">#阅读量</span></span><br><span class="line"> bcomment = models.IntegerField(default=<span class="number">0</span>)<span class="comment">#评论量</span></span><br><span class="line"> isDelete = models.BooleanField(default=<span class="keyword">False</span>)<span class="comment">#逻辑删除</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#定义英雄模型类HeroInfo</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HeroInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> hname = models.CharField(max_length=<span class="number">20</span>)<span class="comment">#英雄姓名</span></span><br><span class="line"> hgender = models.BooleanField(default=<span class="keyword">True</span>)<span class="comment">#英雄性别</span></span><br><span class="line"> isDelete = models.BooleanField(default=<span class="keyword">False</span>)<span class="comment">#逻辑删除</span></span><br><span class="line"> hcomment = models.CharField(max_length=<span class="number">200</span>)<span class="comment">#英雄描述信息</span></span><br><span class="line"> hbook = models.ForeignKey(<span class="string">'BookInfo'</span>)<span class="comment">#英雄与图书表的关系为一对多,所以属性定义在英雄模型类中</span></span><br></pre></td></tr></table></figure><p><strong>2.迁移</strong></p><p>生成迁移文件。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python manage.py makemigrations</span><br></pre></td></tr></table></figure><p>生成迁移文件的时候出现错误,把数据库切换成了mysql,需要安装pymysql模块之后,Django框架才可以操作mysql数据库。安装命令如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pymysql</span><br></pre></td></tr></table></figure><p>安装成功之后,在test2/__init__.py文件中加上如下代码:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">import pymysql</span><br><span class="line">pymysql.install_as_MySQLdb()</span><br></pre></td></tr></table></figure><p>然后执行如下命令。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python manage.py makemigrations <span class="comment"># 生成迁移文件</span></span><br><span class="line">python manage.py migrate <span class="comment"># 开始迁移</span></span><br></pre></td></tr></table></figure><p><strong>3. 运行服务器</strong></p><p>当你运行服务器的时候,可能会报连接不上数据库的问题 :</p><p><img src="https://s1.ax1x.com/2018/08/13/Pg9unI.png" alt="数据库权限问题"></p><h3 id="测试数据"><a href="#测试数据" class="headerlink" title="测试数据"></a>测试数据</h3><p>在数据库命令行中,复制如下语句执行,向booktest_bookinfo表中插入测试数据</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> booktest_bookinfo(btitle,bpub_date,bread,bcomment,isDelete) <span class="keyword">values</span></span><br><span class="line">(<span class="string">'射雕英雄传'</span>,<span class="string">'1980-5-1'</span>,<span class="number">12</span>,<span class="number">34</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'天龙八部'</span>,<span class="string">'1986-7-24'</span>,<span class="number">36</span>,<span class="number">40</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'笑傲江湖'</span>,<span class="string">'1995-12-24'</span>,<span class="number">20</span>,<span class="number">80</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'雪山飞狐'</span>,<span class="string">'1987-11-11'</span>,<span class="number">58</span>,<span class="number">24</span>,<span class="number">0</span>);</span><br></pre></td></tr></table></figure><p>再复制如下语句执行,向booktest_heroinfo表中插入测试数据:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> booktest_heroinfo(hname,hgender,hbook_id,hcomment,isDelete) <span class="keyword">values</span></span><br><span class="line">(<span class="string">'郭靖'</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="string">'降龙十八掌'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'黄蓉'</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="string">'打狗棍法'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'黄药师'</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="string">'弹指神通'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'欧阳锋'</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="string">'蛤蟆功'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'梅超风'</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="string">'九阴白骨爪'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'乔峰'</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="string">'降龙十八掌'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'段誉'</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="string">'六脉神剑'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'虚竹'</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="string">'天山六阳掌'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'王语嫣'</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="string">'神仙姐姐'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'令狐冲'</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="string">'独孤九剑'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'任盈盈'</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="string">'弹琴'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'岳不群'</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="string">'华山剑法'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'东方不败'</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="string">'葵花宝典'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'胡斐'</span>,<span class="number">1</span>,<span class="number">4</span>,<span class="string">'胡家刀法'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'苗若兰'</span>,<span class="number">0</span>,<span class="number">4</span>,<span class="string">'黄衣'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'程灵素'</span>,<span class="number">0</span>,<span class="number">4</span>,<span class="string">'医术'</span>,<span class="number">0</span>),</span><br><span class="line">(<span class="string">'袁紫衣'</span>,<span class="number">0</span>,<span class="number">4</span>,<span class="string">'六合拳'</span>,<span class="number">0</span>);</span><br></pre></td></tr></table></figure><h3 id="定义视图"><a href="#定义视图" class="headerlink" title="定义视图"></a>定义视图</h3><p>打开booktest/views.py文件,定义视图代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> render,redirect</span><br><span class="line"><span class="keyword">from</span> booktest.models <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> date</span><br><span class="line"></span><br><span class="line"><span class="comment">#查询所有图书并显示</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> list=BookInfo.objects.all()</span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/index.html'</span>,{<span class="string">'list'</span>:list})</span><br><span class="line"></span><br><span class="line"><span class="comment">#创建新图书</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">create</span><span class="params">(request)</span>:</span></span><br><span class="line"> book=BookInfo()</span><br><span class="line"> book.btitle = <span class="string">'流星蝴蝶剑'</span></span><br><span class="line"> book.bpub_date = date(<span class="number">1995</span>,<span class="number">12</span>,<span class="number">30</span>)</span><br><span class="line"> book.save()</span><br><span class="line"> <span class="comment">#转向到首页</span></span><br><span class="line"> <span class="keyword">return</span> redirect(<span class="string">'/'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">#逻辑删除指定编号的图书</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">delete</span><span class="params">(request,id)</span>:</span></span><br><span class="line"> book=BookInfo.objects.get(id=int(id))</span><br><span class="line"> book.delete()</span><br><span class="line"> <span class="comment">#转向到首页</span></span><br><span class="line"> <span class="keyword">return</span> redirect(<span class="string">'/'</span>)</span><br></pre></td></tr></table></figure><h3 id="配置url"><a href="#配置url" class="headerlink" title="配置url"></a>配置url</h3><p>打开test2/urls.py文件,配置url如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> include, url</span><br><span class="line"><span class="keyword">from</span> django.contrib <span class="keyword">import</span> admin</span><br><span class="line"></span><br><span class="line">urlpatterns = [</span><br><span class="line"> url(<span class="string">r'^admin/'</span>, include(admin.site.urls)),</span><br><span class="line"> <span class="comment">#引入booktest的url配置</span></span><br><span class="line"> url(<span class="string">r'^'</span>,include(<span class="string">'booktest.urls'</span>)),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>在booktest应用下创建urls.py文件,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url</span><br><span class="line"><span class="keyword">from</span> booktest <span class="keyword">import</span> views</span><br><span class="line"></span><br><span class="line">urlpatterns=[</span><br><span class="line"> url(<span class="string">r'^$'</span>,views.index),</span><br><span class="line"> url(<span class="string">r'^delete(\d+)/$'</span>,views.delete),</span><br><span class="line"> url(<span class="string">r'^create/$'</span>,views.create),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><h3 id="创建模板"><a href="#创建模板" class="headerlink" title="创建模板"></a>创建模板</h3><p>打开test2/settings.py文件,配置模板查找目录TEMPLATES的DIRS。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'DIRS'</span>: [os.path.join(BASE_DIR,<span class="string">'templates'</span>)],</span><br></pre></td></tr></table></figure><p>创建templates/booktest/index.html文件。</p><p>模板代码如下:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><html></span><br><span class="line"><head></span><br><span class="line"> <title>复习案例</title></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line"><a href="/create/">创建</a></span><br><span class="line"><ul></span><br><span class="line">{%<span class="keyword">for</span> book <span class="keyword">in</span> list%}</span><br><span class="line"> <li>{{book.btitle}}--<a href="/delete{{book.id}}/">删除</a></li></span><br><span class="line">{%endfor%}</span><br><span class="line"></ul></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><h3 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h3><p>运行服务器。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ python manage.py runserver</span><br></pre></td></tr></table></figure><p>在浏览器中查看:</p><p><img src="https://s1.ax1x.com/2018/08/13/Pg9WHx.png" alt="运行服务器"></p><p>在mysql命令行中查看数据表变化如下图:</p><p><img src="https://s1.ax1x.com/2018/08/13/Pg94UK.png" alt="数据表变化"></p><h2 id="模型类定义属性"><a href="#模型类定义属性" class="headerlink" title="模型类定义属性"></a>模型类定义属性</h2><h3 id="属性特性"><a href="#属性特性" class="headerlink" title="属性特性"></a>属性特性</h3><p><strong>Django根据属性的类型确定以下信息:</strong></p><ul><li>当前选择的数据库支持字段的类型</li><li>渲染管理表单时使用的默认html控件</li><li>在管理站点最低限度的验证</li></ul><p>django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。</p><p><strong>属性命名限制: </strong></p><ul><li>不能是python的保留关键字。</li><li>不允许使用连续的下划线,这是由django的查询方式决定的,在第4节会详细讲解查询。</li><li>定义属性时需要指定字段类型,通过字段类型的参数指定选项</li></ul><h3 id="字段类型及选项"><a href="#字段类型及选项" class="headerlink" title="字段类型及选项"></a>字段类型及选项</h3><p><strong>字段类型</strong></p><p>使用时需要引入django.db.models包,字段类型如下:</p><ul><li>AutoField:自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。</li><li>BooleanField:布尔字段,值为True或False。</li><li>NullBooleanField:支持Null、True、False三种值。</li><li>CharField(max_length=字符长度):字符串。 参数max_length表示最大字符个数。</li><li>TextField:大文本字段,一般超过4000个字符时使用。</li><li>IntegerField:整数。</li><li>DecimalField(max_digits=None, decimal_places=None):十进制浮点数。<ul><li>参数max_digits表示总位数。</li><li>参数decimal_places表示小数位数。</li></ul></li><li>DateField[auto_now=False, auto_now_add=False]):日期。<ul><li>参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于”最后一次修改”的时间戳,它总是使用当前日期,默认为false。</li><li>参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。</li><li>参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。</li></ul></li><li>TimeField:时间,参数同DateField。</li><li>DateTimeField:日期时间,参数同DateField。</li><li>FileField:上传文件字段。</li><li>ImageField:继承于FileField,对上传的内容进行校验,确保是有效的图片。</li></ul><p><strong>字段选项</strong></p><p>通过选项实现对字段的约束,选项如下:</p><ul><li>null:如果为True,表示允许为空,默认值是False。</li><li>blank:如果为True,则该字段允许为空白,默认值是False。</li><li><strong>对比:null是数据库范畴的概念,blank是表单验证范畴的</strong>。</li><li>db_column:字段的名称,如果未指定,则使用属性的名称。</li><li>db_index:若值为True, 则在表中会为此字段创建索引,默认值是False。</li><li>default:默认值。</li><li>primary_key:若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用。</li><li>unique:如果为True, 这个字段在表中必须有唯一值,默认值是False。</li></ul><h3 id="综合演示"><a href="#综合演示" class="headerlink" title="综合演示"></a>综合演示</h3><p>修改booktest/models.py中的模型类,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="comment">#定义图书模型类BookInfo</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> <span class="comment">#btitle = models.CharField(max_length=20)#图书名称</span></span><br><span class="line"> btitle = models.CharField(max_length=<span class="number">20</span>, db_column=<span class="string">'title'</span>)<span class="comment">#通过db_column指定btitle对应表格中字段的名字为title</span></span><br><span class="line"> bpub_date = models.DateField()<span class="comment">#发布日期</span></span><br><span class="line"> bread = models.IntegerField(default=<span class="number">0</span>)<span class="comment">#阅读量</span></span><br><span class="line"> bcomment = models.IntegerField(default=<span class="number">0</span>)<span class="comment">#评论量</span></span><br><span class="line"> isDelete = models.BooleanField(default=<span class="keyword">False</span>)<span class="comment">#逻辑删除</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#定义英雄模型类HeroInfo</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HeroInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> hname = models.CharField(max_length=<span class="number">20</span>)<span class="comment">#英雄姓名</span></span><br><span class="line"> hgender = models.BooleanField(default=<span class="keyword">True</span>)<span class="comment">#英雄性别</span></span><br><span class="line"> isDelete = models.BooleanField(default=<span class="keyword">False</span>)<span class="comment">#逻辑删除</span></span><br><span class="line"> <span class="comment">#hcomment = models.CharField(max_length=200)#英雄描述信息</span></span><br><span class="line"> hcomment = models.CharField(max_length=<span class="number">200</span>, null=<span class="keyword">True</span>, blank=<span class="keyword">False</span>) <span class="comment">#hcomment对应的数据库中的字段可以为空,但通过后台管理页面添加英雄信息时hcomment对应的输入框不能为空</span></span><br><span class="line"> hbook = models.ForeignKey(<span class="string">'BookInfo'</span>)<span class="comment">#英雄与图书表的关系为一对多,所以属性定义在英雄模型类中</span></span><br></pre></td></tr></table></figure><p>然后生成迁移文件并执行迁移命令,最后查看test2数据库中的内容。</p><h2 id="条件查询"><a href="#条件查询" class="headerlink" title="条件查询"></a>条件查询</h2><blockquote><p>实现sql中where的功能,调用过滤器filter()、exclude()、get(),下面以filter()为例。通过”属性名_id”表示外键对应对象的id值。</p></blockquote><p>语法如下:</p><blockquote><p>说明:属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线。</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">属性名称__比较运算符=值</span><br></pre></td></tr></table></figure><h3 id="查看MySQL日志"><a href="#查看MySQL日志" class="headerlink" title="查看MySQL日志"></a>查看MySQL日志</h3><p>查看mysql数据库日志可以查看对数据库的操作记录。 mysql日志文件默认没有产生,需要做如下配置:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">vi /etc/mysql/mysql.conf.d/mysqld.conf</span><br><span class="line"><span class="meta">#</span><span class="bash"> 打开68,69行日志记录</span></span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/08/13/PgPnTP.png" alt="mysql日志"></p><p>使用如下命令打开mysql日志文件:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tail -f /var/<span class="built_in">log</span>/mysql/mysql.log <span class="comment">#可以实时查看数据库的日志内容</span></span><br></pre></td></tr></table></figure><h3 id="条件运算符"><a href="#条件运算符" class="headerlink" title="条件运算符"></a>条件运算符</h3><p>1) 查询等</p><p><strong>exact:表示判等。</strong></p><p>例:查询编号为1的图书。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 先进入shell交互式命令行</span></span><br><span class="line">$ python manage.py shell</span><br><span class="line">list=BookInfo.objects.filter(id__exact=1)</span><br><span class="line">可简写为:</span><br><span class="line">list=BookInfo.objects.filter(id=1)</span><br></pre></td></tr></table></figure><p>2) 模糊查询</p><p><strong>contains:是否包含。</strong></p><p>例:查询书名包含’传’的图书。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(btitle__contains=<span class="string">'传'</span>)</span><br></pre></td></tr></table></figure><p><strong>startswith、endswith:以指定值开头或结尾。</strong></p><p>例:查询书名以’部’结尾的图书</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(btitle__endswith=<span class="string">'部'</span>)</span><br></pre></td></tr></table></figure><p>3) 空查询</p><p><strong>isnull:是否为null。</strong></p><p>例:查询书名不为空的图书。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(btitle__isnull=False)</span><br></pre></td></tr></table></figure><p>4) 范围查询</p><p><strong>in:是否包含在范围内。</strong></p><p>例:查询编号为1或3或5的图书</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(id__in=[1, 3, 5])</span><br></pre></td></tr></table></figure><p>5) 比较查询</p><p><strong>gt、gte、lt、lte:大于、大于等于、小于、小于等于。</strong></p><p>例:查询编号大于3的图书</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(id__gt=3)</span><br></pre></td></tr></table></figure><p><strong>不等于的运算符,使用exclude()过滤器。</strong></p><p>例:查询编号不等于3的图书</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.exclude(id=3)</span><br></pre></td></tr></table></figure><p>6) 日期查询</p><p><strong>year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。</strong></p><p>例:查询1980年发表的图书。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(bpub_date__year=1980)</span><br></pre></td></tr></table></figure><p>例:查询1980年1月1日后发表的图书。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))</span><br></pre></td></tr></table></figure><h3 id="F对象"><a href="#F对象" class="headerlink" title="F对象"></a>F对象</h3><p>之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢? 答:使用F对象,被定义在django.db.models中。</p><p>例:查询阅读量大于等于评论量的图书。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db.models <span class="keyword">import</span> F</span><br><span class="line">list = BookInfo.objects.filter(bread__gte=F(<span class="string">'bcomment'</span>))</span><br></pre></td></tr></table></figure><h3 id="Q对象"><a href="#Q对象" class="headerlink" title="Q对象"></a>Q对象</h3><p>多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。</p><p>例:查询阅读量大于20,并且编号小于3的图书。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">list=BookInfo.objects.filter(bread__gt=<span class="number">20</span>,id__lt=<span class="number">3</span>)</span><br><span class="line">或</span><br><span class="line">list=BookInfo.objects.filter(bread__gt=<span class="number">20</span>).filter(id__lt=<span class="number">3</span>)</span><br></pre></td></tr></table></figure><p>如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符,Q对象被义在django.db.models中。</p><p>语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Q(属性名__运算符=值)</span><br></pre></td></tr></table></figure><p>例:查询阅读量大于20的图书,改写为Q对象如下。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db.models <span class="keyword">import</span> Q</span><br><span class="line">list = BookInfo.objects.filter(Q(bread__gt=<span class="number">20</span>))</span><br></pre></td></tr></table></figure><p>Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。</p><p>例:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))</span><br></pre></td></tr></table></figure><p>Q对象前可以使用~操作符,表示非not。</p><p>例:查询编号不等于3的图书。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(~Q(pk=3))</span><br></pre></td></tr></table></figure><h3 id="聚合函数"><a href="#聚合函数" class="headerlink" title="聚合函数"></a>聚合函数</h3><p>使用aggregate()过滤器调用聚合函数。聚合函数包括:Avg,Count,Max,Min,Sum,被定义在django.db.models中。</p><p>例:查询图书的总阅读量。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db.models <span class="keyword">import</span> Sum</span><br><span class="line">list = BookInfo.objects.aggregate(Sum(<span class="string">'bread'</span>))</span><br></pre></td></tr></table></figure><p>注意aggregate的返回值是一个字典类型,格式如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">{'聚合类小写__属性名':值}</span><br><span class="line">如:{'sum__bread':3}</span><br></pre></td></tr></table></figure><p>使用count时一般不使用aggregate()过滤器。</p><p>例:查询图书总数。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.count()</span><br></pre></td></tr></table></figure><p>注意count函数的返回值是一个数字。</p><h2 id="查询集"><a href="#查询集" class="headerlink" title="查询集"></a>查询集</h2><blockquote><p>查询集表示从数据库中获取的对象集合,在管理器上调用某些过滤器方法会返回查询集,查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果,从Sql的角度,查询集和select语句等价,过滤器像where和limit子句。</p></blockquote><h3 id="查询集的过滤器"><a href="#查询集的过滤器" class="headerlink" title="查询集的过滤器"></a>查询集的过滤器</h3><p><strong>返回查询集的过滤器如下</strong>:</p><ul><li>all():返回所有数据。</li><li>filter():返回满足条件的数据。</li><li>exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字。</li><li>order_by():对结果进行排序。</li></ul><p><strong>返回单个值的过滤器如下</strong>:</p><ul><li>get():返回单个满足条件的对象<ul><li>如果未找到会引发”模型类.DoesNotExist”异常。</li><li>如果多条被返回,会引发”模型类.MultipleObjectsReturned”异常。</li></ul></li><li>count():返回当前查询结果的总条数。</li><li>aggregate():聚合,返回一个字典。</li></ul><p><strong>判断某一个查询集中是否有数据</strong>:</p><ul><li>exists():判断查询集中是否有数据,如果有则返回True,没有则返回False。</li></ul><h3 id="查询集的特性"><a href="#查询集的特性" class="headerlink" title="查询集的特性"></a>查询集的特性</h3><ul><li>惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用。</li><li>缓存:使用同一个查询集,第一次使用时会发生数据库的查询,然后把结果缓存下来,再次使用这个查询集时会使用缓存的数据。</li></ul><h3 id="限制查询集"><a href="#限制查询集" class="headerlink" title="限制查询集"></a>限制查询集</h3><p>可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。</p><blockquote><p>注意:不支持负数索引。</p></blockquote><p>对查询集进行切片后返回一个新的查询集,不会立即执行查询。</p><p>如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()如果没有数据引发DoesNotExist异常。</p><h2 id="模型类关系"><a href="#模型类关系" class="headerlink" title="模型类关系"></a>模型类关系</h2><h3 id="关系字段类型"><a href="#关系字段类型" class="headerlink" title="关系字段类型"></a>关系字段类型</h3><p>关系型数据库的关系包括三种类型:</p><ul><li>ForeignKey:一对多,将字段定义在多的一端中。</li><li>ManyToManyField:多对多,将字段定义在任意一端中。</li><li>OneToOneField:一对一,将字段定义在任意一端中。</li><li>可以维护递归的关联关系,使用’self’指定,详见”自关联”。</li></ul><h3 id="一对多关系"><a href="#一对多关系" class="headerlink" title="一对多关系"></a>一对多关系</h3><p>参见booktest应用中的BookInfo类和HeroInfo类。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#定义图书模型类BookInfo</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> btitle = models.CharField(max_length=<span class="number">20</span>)<span class="comment">#图书名称</span></span><br><span class="line"> bpub_date = models.DateField()<span class="comment">#发布日期</span></span><br><span class="line"> bread = models.IntegerField(default=<span class="number">0</span>)<span class="comment">#阅读量</span></span><br><span class="line"> bcomment = models.IntegerField(default=<span class="number">0</span>)<span class="comment">#评论量</span></span><br><span class="line"> isDelete = models.BooleanField(default=<span class="keyword">False</span>)<span class="comment">#逻辑删除</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#定义英雄模型类HeroInfo</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HeroInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> hname = models.CharField(max_length=<span class="number">20</span>)<span class="comment">#英雄姓名</span></span><br><span class="line"> hgender = models.BooleanField(default=<span class="keyword">True</span>)<span class="comment">#英雄性别</span></span><br><span class="line"> isDelete = models.BooleanField(default=<span class="keyword">False</span>)<span class="comment">#逻辑删除</span></span><br><span class="line"> hcomment = models.CharField(max_length=<span class="number">200</span>)<span class="comment">#英雄描述信息</span></span><br><span class="line"> hbook = models.ForeignKey(<span class="string">'BookInfo'</span>)<span class="comment">#英雄与图书表的关系为一对多,所以属性定义在英雄模型类中</span></span><br></pre></td></tr></table></figure><h3 id="多对多关系"><a href="#多对多关系" class="headerlink" title="多对多关系"></a>多对多关系</h3><p>我们下面设计一个新闻类和新闻类型类,一个新闻类型下可以用很多条新闻,一条新闻也可能归属于多种新闻类型。重新在项目test2下新建一个应用newstest,注册应用之后,编辑newstest/models.py文件设计模型类。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TypeInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> tname = models.CharField(max_length=<span class="number">20</span>) <span class="comment">#新闻类别</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">NewsInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> ntitle = models.CharField(max_length=<span class="number">60</span>) <span class="comment">#新闻标题</span></span><br><span class="line"> ncontent = models.TextField() <span class="comment">#新闻内容</span></span><br><span class="line"> npub_date = models.DateTimeField(auto_now_add=<span class="keyword">True</span>) <span class="comment">#新闻发布时间</span></span><br><span class="line"> ntype = models.ManyToManyField(<span class="string">'TypeInfo'</span>) <span class="comment">#通过ManyToManyField建立TypeInfo类和NewsInfo类之间多对多的关系</span></span><br></pre></td></tr></table></figure><h3 id="关联查询"><a href="#关联查询" class="headerlink" title="关联查询"></a>关联查询</h3><h4 id="通过对象执行关联查询"><a href="#通过对象执行关联查询" class="headerlink" title="通过对象执行关联查询"></a>通过对象执行关联查询</h4><p>在定义模型类时,可以指定三种关联关系,最常用的是一对多关系,如本例中的”图书-英雄”就为一对多关系,接下来进入shell练习关系的查询。</p><p>由一到多的访问语法:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 一对应的模型类对象.多对应的模型类名小写_set (bookinfo-heroinf)</span></span><br><span class="line">例:</span><br><span class="line">b = BookInfo.objects.get(id=1)</span><br><span class="line">b.heroinfo_set.all()</span><br></pre></td></tr></table></figure><p>由多到一的访问语法:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">多对应的模型类对象.多对应的模型类中的关系类属性名</span><br><span class="line">例:</span><br><span class="line">h = HeroInfo.objects.get(id=1)</span><br><span class="line">h.hbook</span><br></pre></td></tr></table></figure><p>访问一对应的模型类关联对象的id语法:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">多对应的模型类对象.关联类属性_id</span><br><span class="line">例:</span><br><span class="line">h = HeroInfo.objects.get(id=1)</span><br><span class="line">h.book_id</span><br></pre></td></tr></table></figure><p><strong>由一类查多类</strong></p><p>例:查询编号为1的图书。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">book=BookInfo.objects.get(pk=1)</span><br></pre></td></tr></table></figure><p>例:获得book图书的所有英雄。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">book.heroinfo_set.all()</span><br></pre></td></tr></table></figure><p><strong>由多类查一类</strong></p><p>例:获得编号为1的英雄。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hero=HeroInfo.objects.get(pk=1)</span><br></pre></td></tr></table></figure><p>例:获得hero英雄出自的图书。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hero.hbook</span><br></pre></td></tr></table></figure><h4 id="通过模型类执行关联查询"><a href="#通过模型类执行关联查询" class="headerlink" title="通过模型类执行关联查询"></a>通过模型类执行关联查询</h4><p><strong>由多模型类条件查询一模型类数据</strong>:</p><p>语法如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">关联模型类名小写__属性名__条件运算符=值</span><br></pre></td></tr></table></figure><blockquote><p>如果没有”__运算符”部分,表示等于,结果和sql中的inner join相同。</p></blockquote><p>例:查询图书,要求图书中英雄的描述包含’八’。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = BookInfo.objects.filter(heroinfo__hcontent__contains='八')</span><br></pre></td></tr></table></figure><p><strong>由一模型类条件查询多模型类数据</strong>:</p><p>语法如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">一模型类关联属性名__一模型类属性名__条件运算符=值</span><br></pre></td></tr></table></figure><p>例:查询书名为“天龙八部”的所有英雄。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">list = HeroInfo.objects.filter(hbook__btitle='天龙八部')</span><br></pre></td></tr></table></figure><h3 id="自关联"><a href="#自关联" class="headerlink" title="自关联"></a>自关联</h3><blockquote><p>对于地区信息、分类信息等数据,表结构非常类似,每个表的数据量十分有限,为了充分利用数据表的大量数据存储功能,可以设计成一张表,内部的关系字段指向本表的主键,这就是自关联的表结构。</p></blockquote><p>打开booktest/models.py文件,定义AreaInfo类。</p><blockquote><p>说明:关系属性使用self指向本类,要求null和blank允许为空,因为一级数据是没有父级的。</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#定义地区模型类,存储省、市、区县信息</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AreaInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> atitle=models.CharField(max_length=<span class="number">30</span>)<span class="comment">#名称</span></span><br><span class="line"> aParent=models.ForeignKey(<span class="string">'self'</span>,null=<span class="keyword">True</span>,blank=<span class="keyword">True</span>)<span class="comment">#关系</span></span><br></pre></td></tr></table></figure><p>迁移:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">python manage.py makemigrations</span><br><span class="line">python manage.py migrate</span><br></pre></td></tr></table></figure><p> 打开mysql命令行,导入数据。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">source</span> areas.sql <span class="comment"># 这里的数据找我要</span></span><br></pre></td></tr></table></figure><p>打开booktest/views.py文件,定义视图area。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">from booktest.models import AreaInfo</span><br><span class="line">...</span><br><span class="line"><span class="comment">#查询广州市的信息</span></span><br><span class="line">def area(request):</span><br><span class="line"> area = AreaInfo.objects.get(pk=440100)</span><br><span class="line"> <span class="built_in">return</span> render(request, <span class="string">'booktest/area.html'</span>, {<span class="string">'area'</span>: area})</span><br></pre></td></tr></table></figure><p>打开booktest/urls.py文件,新建一条url。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">urlpatterns = [</span><br><span class="line"> url(r'^area/$', views.area),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>在templates/booktest目录下,新建area.html文件。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>地区<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line">当前地区:{{area.atitle}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>/></span></span><br><span class="line">上级地区:{{area.aParent.atitle}}</span><br><span class="line"><span class="tag"><<span class="name">hr</span>/></span></span><br><span class="line">下级地区:</span><br><span class="line"><span class="tag"><<span class="name">ul</span>></span></span><br><span class="line"> {%for a in area.areainfo_set.all%}</span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span>{{a.atitle}}<span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> {%endfor%}</span><br><span class="line"><span class="tag"></<span class="name">ul</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure><p>运行服务器。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python manage.py runserver</span><br></pre></td></tr></table></figure><p>在浏览器中输出效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/13/PgiZ3F.png" alt="自关联"></p><h2 id="模型类的扩展"><a href="#模型类的扩展" class="headerlink" title="模型类的扩展"></a>模型类的扩展</h2><h3 id="模型实例方法"><a href="#模型实例方法" class="headerlink" title="模型实例方法"></a>模型实例方法</h3><ul><li>str():在将对象转换成字符串时会被调用。</li><li>save():将模型对象保存到数据表中,ORM框架会转换成对应的insert或update语句。</li><li>delete():将模型对象从数据表中删除,ORM框架会转换成对应的delete语句。</li></ul><h3 id="模型类的属性"><a href="#模型类的属性" class="headerlink" title="模型类的属性"></a>模型类的属性</h3><p>属性objects:管理器,是models.Manager类型的对象,用于与数据库进行交互。</p><blockquote><p>当没有为模型类定义管理器时,Django会为每一个模型类生成一个名为objects的管理器,自定义管理器后,Django不再生成默认管理器objects。</p></blockquote><p>为模型类BookInfo定义管理器books语法如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> ...</span><br><span class="line"> books = models.Manager()</span><br></pre></td></tr></table></figure><h3 id="管理器Manager"><a href="#管理器Manager" class="headerlink" title="管理器Manager"></a>管理器Manager</h3><p>管理器是Django的模型进行数据库操作的接口,Django应用的每个模型类都拥有至少一个管理器。Django支持自定义管理器类,继承自models.Manager。</p><p>自定义管理器类主要用于两种情况:</p><ul><li>1.修改原始查询集,重写all()方法</li><li>2.向管理器类中添加额外的方法,如向数据库中插入数据。</li></ul><p><strong>1.修改原始查询集,重写all()方法 </strong></p><p>a)打开booktest/models.py文件,定义类BookInfoManager</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#图书管理器</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfoManager</span><span class="params">(models.Manager)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">all</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="comment">#默认查询未删除的图书信息</span></span><br><span class="line"> <span class="comment">#调用父类的成员语法为:super().方法名</span></span><br><span class="line"> <span class="keyword">return</span> super().all().filter(isDelete=<span class="keyword">False</span>)</span><br></pre></td></tr></table></figure><p>b)在模型类BookInfo中定义管理器</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">class BookInfo(models.Model):</span><br><span class="line"> books = BookInfoManager()</span><br></pre></td></tr></table></figure><p><strong>2.在管理器类中定义创建对象的方法</strong></p><p>对模型类对应的数据表进行操作时,推荐将这些操作数据表的方法封装起来,放到模型管理器类中。</p><p>a)打开booktest/models.py文件,定义方法create。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfoManager</span><span class="params">(models.Manager)</span>:</span></span><br><span class="line"> ...</span><br><span class="line"> <span class="comment">#创建模型类,接收参数为属性赋值</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">create_book</span><span class="params">(self, title, pub_date)</span>:</span></span><br><span class="line"> <span class="comment">#创建模型类对象self.model可以获得模型类</span></span><br><span class="line"> book = self.model()</span><br><span class="line"> book.btitle = title</span><br><span class="line"> book.bpub_date = pub_date</span><br><span class="line"> book.bread=<span class="number">0</span></span><br><span class="line"> book.bcommet=<span class="number">0</span></span><br><span class="line"> book.isDelete = <span class="keyword">False</span></span><br><span class="line"> <span class="comment"># 将数据插入进数据表</span></span><br><span class="line"> book.save()</span><br><span class="line"> <span class="keyword">return</span> book</span><br></pre></td></tr></table></figure><p>b)为模型类BookInfo定义管理器books语法如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> books = BookInfoManager()</span><br></pre></td></tr></table></figure><p>c)调用语法如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 调用</span></span><br><span class="line">book=BookInfo.books.create_book(<span class="string">"abc"</span>,date(<span class="number">1980</span>,<span class="number">1</span>,<span class="number">1</span>))</span><br></pre></td></tr></table></figure><h3 id="元选项"><a href="#元选项" class="headerlink" title="元选项"></a>元选项</h3><p>在模型类中定义类Meta,用于设置元信息,如使用db_table自定义表的名字。</p><p>数据表的默认名称为:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><app_name>_<model_name></span><br><span class="line">例:</span><br><span class="line">booktest_bookinfo</span><br></pre></td></tr></table></figure><p><strong>例:指定BookInfo模型类生成的数据表名为bookinfo。</strong></p><p>在BookInfo模型类中添加如下内容,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#定义图书模型类BookInfo</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> ...</span><br><span class="line"></span><br><span class="line"> <span class="comment">#定义元选项</span></span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">Meta</span>:</span></span><br><span class="line"> db_table=<span class="string">'bookinfo'</span> <span class="comment">#指定BookInfo生成的数据表名为bookinfo</span></span><br></pre></td></tr></table></figure><h2 id="重要知识点总结"><a href="#重要知识点总结" class="headerlink" title="重要知识点总结"></a>重要知识点总结</h2><ul><li>修改配置文件使用mysql数据库</li><li>属性类型及选项</li><li>条件查询和查询集</li><li>模型类关联</li><li>关联查询</li><li>自定义管理器及用途</li><li>元选项</li></ul>]]></content>
<summary type="html">
<h2 id="ORM简介"><a href="#ORM简介" class="headerlink" title="ORM简介"></a>ORM简介</h2><blockquote>
<p>ORM,全拼Object-Relation Mapping,中文意为对象-关系映射,是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射ORM系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。O/R中字母O起源于”对象”(Object),而R则来自于”关系”(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。</p>
</blockquote>
<h3 id="ORM的好处"><a href="#ORM的好处" class="headerlink" title="ORM的好处"></a>ORM的好处</h3><p>在MVC框架中的Model模块中都包括ORM,对于开发人员主要带来了如下好处:</p>
<ul>
<li>实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码。</li>
<li>只需要面向对象编程,不需要面向数据库编写代码。</li>
<li>在MVC中Model中定义的类,通过ORM与关系型数据库中的表对应,对象的属性体现对象间的关系,这种关系也被映射到数据表中。</li>
</ul>
<h3 id="ORM示意图"><a href="#ORM示意图" class="headerlink" title="ORM示意图"></a>ORM示意图</h3><p><img src="https://s1.ax1x.com/2018/08/13/Pgp8yR.png" alt="ORM示意图"></p>
</summary>
<category term="Django入门" scheme="http://www.chenfanlinux.org/categories/Django%E5%85%A5%E9%97%A8/"/>
<category term="Django" scheme="http://www.chenfanlinux.org/tags/Django/"/>
</entry>
<entry>
<title>Django基础入门</title>
<link href="http://www.chenfanlinux.org/2018/08/10/Django%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/"/>
<id>http://www.chenfanlinux.org/2018/08/10/Django基础入门/</id>
<published>2018-08-10T02:47:14.000Z</published>
<updated>2018-08-10T02:55:05.000Z</updated>
<content type="html"><![CDATA[<h2 id="认识Django"><a href="#认识Django" class="headerlink" title="认识Django"></a>认识Django</h2><h3 id="Django简介"><a href="#Django简介" class="headerlink" title="Django简介"></a>Django简介</h3><p>Django,发音为[`dʒæŋɡəʊ],是用python语言写的开源web开发框架,并遵循MVC设计。劳伦斯出版集团为了开发以新闻内容为主的网站,而开发出来了这个框架,于2005年7月在BSD许可证下发布。这个名称来源于比利时的爵士音乐家DjangoReinhardt,他是一个吉普赛人,主要以演奏吉它为主,还演奏过小提琴等。由于Django在近年来的迅速发展,应用越来越广泛,被著名IT开发杂志SDTimes评选为2013SDTimes100,位列”API、库和框架”分类第6位,被认为是该领域的佼佼者。Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以”插件”形式服务于整个框架,Django有许多功能强大的第三方插件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展性。它还强调快速开发和DRY(DoNotRepeatYourself)原则。</p><blockquote><p>点击查看<a href="https://www.djangoproject.com/" target="_blank" rel="noopener">django官方网站</a></p><p>点击查看<a href="https://github.com/django/django" target="_blank" rel="noopener">django源码</a></p><p>点击查看<a href="https://yiyibooks.cn/xx/django_182/index.html" target="_blank" rel="noopener">1.8.2官方中文文档</a></p></blockquote><h3 id="MVC简介"><a href="#MVC简介" class="headerlink" title="MVC简介"></a>MVC简介</h3><p>MVC的全拼为Model-View-Controller,最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式,是为了将传统的输入(input)、处理(processing)、输出(output)任务运用到图形化用户交互模型中而设计的。随着标准输入输出设备的出现,开发人员只需要将精力集中在业务逻辑的分析与实现上。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。现在虽然不再使用原来的分工方式,但是这种<strong>分工的思想</strong>被沿用下来,广泛应用于软件工程中,是一种典型并且应用广泛的软件架构模式。后来,MVC的思想被应用在了Web开发方面,被称为Web MVC框架。</p><p>MVC框架的核心思想是:<strong>解耦</strong>,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。当前主流的开发语言如Java、PHP、Python中都有MVC框架。</p><h3 id="Web-MVC各部分的功能"><a href="#Web-MVC各部分的功能" class="headerlink" title="Web MVC各部分的功能"></a>Web MVC各部分的功能</h3><ul><li>M全拼为Model,主要封装对数据库层的访问,对数据库中的数据进行增、删、改、查操作。</li><li>V全拼为View,用于封装结果,生成页面展示的html内容。</li><li>C全拼为Controller,用于接收请求,处理业务逻辑,与Model和View交互,返回结果。</li></ul><p><img src="https://s1.ax1x.com/2018/08/09/PyriXF.png" alt="mvc"></p><h3 id="MVT各部分的功能"><a href="#MVT各部分的功能" class="headerlink" title="MVT各部分的功能"></a>MVT各部分的功能</h3><p>Django框架遵循MVC设计,并且有一个专有名词:MVT</p><ul><li>M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。</li><li>V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。</li><li>T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。</li></ul><p><img src="https://s1.ax1x.com/2018/08/09/PyrA0J.png" alt="mvt"></p><a id="more"></a><h2 id="搭建项目虚拟环境"><a href="#搭建项目虚拟环境" class="headerlink" title="搭建项目虚拟环境"></a>搭建项目虚拟环境</h2><h3 id="为什么要使用虚拟环境"><a href="#为什么要使用虚拟环境" class="headerlink" title="为什么要使用虚拟环境?"></a>为什么要使用虚拟环境?</h3><p>在开发过程中,当需要使用python的包时可以联网安装 。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip3 install 包名称</span><br></pre></td></tr></table></figure><p><strong>产生的问题</strong></p><p>如果在一台机器上,想开发多个不同的项目,需要用到同一个包的不同版本,如果还使用上面的命令,在同一个目录下安装或者更新,其它的项目必须就无法运行了,怎么办呢?</p><blockquote><p>解决方案:<strong>虚拟环境</strong>。</p></blockquote><p><strong>什么是虚拟环境呢 </strong></p><p><strong>虚拟环境其实就是对真实pyhton环境的复制</strong>,这样我们在复制的python环境中安装包就不会影响到真实的python环境。通过建立多个虚拟环境,在不同的虚拟环境中开发项目就实现了项目之间的隔离。</p><h3 id="创建虚拟环境"><a href="#创建虚拟环境" class="headerlink" title="创建虚拟环境"></a>创建虚拟环境</h3><p><strong>安装软件包</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> pip3 install virtualenv</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> pip3 install virtualenvwrapper</span></span><br></pre></td></tr></table></figure><p><strong>修改配置</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> vim /root/.bashrc</span></span><br><span class="line">export WORKON_HOME=$HOME/.virtualenvs</span><br><span class="line">source /usr/local/bin/virtualenvwrapper.sh</span><br><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">source</span> /root/.bashrc <span class="comment"># 配置重新加载</span></span></span><br></pre></td></tr></table></figure><p><strong>创建虚拟环境</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 例子: mkvirtualenv -p python3 虚拟环境名称</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> mkvirtualenv -p python3 py3_django</span></span><br></pre></td></tr></table></figure><h3 id="使用虚拟环境"><a href="#使用虚拟环境" class="headerlink" title="使用虚拟环境"></a>使用虚拟环境</h3><p><strong>退出</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 退出虚拟环境的命令如下</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> deactivate</span></span><br></pre></td></tr></table></figure><p><strong>查看与使用</strong></p><p>查看所有虚拟环境的命令如下:</p><blockquote><p>提示:workon后面有个空格,再按两次tab键。</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 进入到所需的虚拟环境</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> workon py3_django</span></span><br></pre></td></tr></table></figure><p><strong>删除</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 先退出:deactivate</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> 再删除:rmvirtualenv py_django</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> rmvirtualenv py3_django</span></span><br></pre></td></tr></table></figure><h3 id="包操作"><a href="#包操作" class="headerlink" title="包操作"></a>包操作</h3><p><strong>安装包</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> pip install 包名称</span></span><br></pre></td></tr></table></figure><p><strong>查看安装的包</strong></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> pip list</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> pip freeze</span></span><br></pre></td></tr></table></figure><p><strong>安装django包</strong></p><p>后面要学习使用django,我们使用的是django1.8.2的版本,这是一个稳定性高、使用广、文档多的版本,<strong>注意</strong>,如果前面删除过虚拟环境py3_django,则需要先创建一下,否则直接安装django包即可。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> pip install django==1.8.2</span></span><br></pre></td></tr></table></figure><h2 id="创建Django项目"><a href="#创建Django项目" class="headerlink" title="创建Django项目"></a>创建Django项目</h2><blockquote><p>我们以一个电商网站为例,网站上有跟用户有关的页面,有跟商品有关的页面,还有跟订单有关的页面,这样的一块内容其实就是网站的一个功能模块。在django中,项目的组织结构为一个项目包含多个<strong>应用</strong>,一个应用对应一个业务模块。</p></blockquote><h3 id="创建项目"><a href="#创建项目" class="headerlink" title="创建项目"></a>创建项目</h3><p>此处在/home/python/pytest/目录下创建项目</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">cd</span> /home/python/</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> mkdir pytest</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">cd</span> pytest</span></span><br></pre></td></tr></table></figure><p>创建项目的命令如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> django-admin startproject 项目名称</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> django-admin startproject test1</span></span><br></pre></td></tr></table></figure><h3 id="项目默认目录说明"><a href="#项目默认目录说明" class="headerlink" title="项目默认目录说明"></a>项目默认目录说明</h3><p>进入test1目录,查看目录树形结构</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> <span class="built_in">cd</span> test1</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> tree</span></span><br></pre></td></tr></table></figure><p>目录结构如下图:</p><p><img src="https://s1.ax1x.com/2018/08/09/PysQCq.png" alt="项目初始目录"></p><p>目录文件说明:</p><ul><li>manage.py是项目管理文件,通过它管理项目。</li><li>与项目同名的目录,此处为test1。</li><li>__init__.py 是一个空文件,作用是这个目录test1可以被当作包使用。</li><li>settings.py 是项目的整体配置文件。</li><li>urls.py 是项目的URL配置文件。</li><li>wsgi.py 是项目与WSGI兼容的Web服务器入口。</li></ul><h3 id="创建项目应用"><a href="#创建项目应用" class="headerlink" title="创建项目应用"></a>创建项目应用</h3><p>使用一个应用开发一个业务模块,此处创建应用名称为booktest,完成图书-英雄的信息维护。</p><p>创建应用的命令如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py startapp booktest</span></span><br></pre></td></tr></table></figure><p>应用初始目录结构如下:</p><p><img src="https://s1.ax1x.com/2018/08/09/PysNVJ.png" alt="应用初始目录"></p><p>应用文件结构说明:</p><ul><li>__init__.py 是一个空文件,作用是这个目录booktest可以被当作包使用。</li><li>tests.py文件用于开发测试用例,在实际开发中会有专门的测试人员,这个事情不需要我们来做。</li><li>models.py文件跟数据库操作相关。</li><li>views.py文件跟接收浏览器请求,进行处理,返回页面相关。</li><li>admin.py文件跟网站的后台管理相关。</li><li>migrations文件夹之后给大家介绍。</li></ul><h3 id="安装应用"><a href="#安装应用" class="headerlink" title="安装应用"></a>安装应用</h3><p>应用创建成功后,需要安装才可以使用,也就是建立应用和项目之间的关联,在test1/settings.py中INSTALLED_APPS下添加应用的名称就可以完成安装。</p><p>初始项目的INSTALLED_APPS如下图:</p><p><img src="https://s1.ax1x.com/2018/08/09/Pys08x.png" alt="安装应用"></p><p>接下来在元组中添加一个新的项,当前示例为booktest</p><p><img src="https://s1.ax1x.com/2018/08/09/PysDxK.png" alt="添加应用"></p><h3 id="开发服务器"><a href="#开发服务器" class="headerlink" title="开发服务器"></a>开发服务器</h3><p>在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用。</p><p> 运行服务器命令如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> $ python manage.py runserver ip:端口</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> python manage.py runserver</span></span><br></pre></td></tr></table></figure><p><strong>可以不写IP和端口,默认IP是127.0.0.1,默认端口为8000</strong>。</p><p>服务器成功启动后如下图:</p><p><img src="https://s1.ax1x.com/2018/08/09/PyshGt.png" alt="服务器启动"></p><p>紧接着在浏览器中输入网址“127.0.0.1:8000”,或者按着ctrl键点击上图中标示出来的地址,可以查看当前站点开发效果。</p><p><img src="https://s1.ax1x.com/2018/08/09/PysbZQ.png" alt="浏览器访问django"></p><h2 id="模型设计"><a href="#模型设计" class="headerlink" title="模型设计"></a>模型设计</h2><blockquote><p>我们之前操作数据库是通过写sql语句,那么能不能不写sql语句就可以操作数据库呢? 可以,就是通过接下来要给大家讲的<strong>ORM框架</strong>。</p></blockquote><h3 id="ORM框架"><a href="#ORM框架" class="headerlink" title="ORM框架"></a>ORM框架</h3><p>O是object,也就<strong>类对象</strong>的意思,R是relation,翻译成中文是关系,也就是关系数据库中<strong>数据表</strong>的意思,M是mapping,是<strong>映射</strong>的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们<strong>通过类和类对象就能操作它所对应的表格中的数据</strong>。ORM框架还有一个功能,它可以<strong>根据我们设计的类自动帮我们生成数据库中的表格</strong>,省去了我们自己建表的过程。</p><p>django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。</p><p><strong>使用django进行数据库开发的步骤如下:</strong></p><ul><li>1.在models.py中定义模型类</li><li>2.迁移</li><li>3.通过类和对象完成数据增删改查操作</li></ul><p>下面我们以保存图书信息为例来给大家介绍Django中进行数据库开发的整个流程。</p><h3 id="定义模型类"><a href="#定义模型类" class="headerlink" title="定义模型类"></a>定义模型类</h3><blockquote><p>模型类定义在models.py文件中,继承自models.Model类。</p></blockquote><p><strong>设计图书类</strong></p><p>图书类:</p><ul><li>类名:BookInfo</li><li>图书名称:btitle</li><li>图书发布日期:bpub_date</li></ul><p><strong>模型类的设计</strong></p><p>根据设计,在models.py中定义模型类如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.db <span class="keyword">import</span> models</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> btitle = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line"> bpub_date = models.DateField()</span><br></pre></td></tr></table></figure><h3 id="迁移"><a href="#迁移" class="headerlink" title="迁移"></a>迁移</h3><p>迁移前目录结构如下图:</p><p><img src="https://s1.ax1x.com/2018/08/09/PyyPZ4.png" alt="迁移前目录结构"></p><p>迁移由两步完成:</p><ul><li>1.生成迁移文件:根据模型类生成创建表的迁移文件。</li><li>2.执行迁移:根据第一步生成的迁移文件在数据库中创建表。</li></ul><p>生成迁移文件命令如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py makemigrations</span></span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/08/09/PyyAiR.png" alt="生成迁移文件"></p><p>执行生成迁移文件命令后,会在应用booktest目录下的migrations目录中生成迁移文件。生成迁移文件后的目录结构:</p><p><img src="https://s1.ax1x.com/2018/08/09/PyymQK.png" alt="迁移命令"></p><p>打开上图中的迁移文件,内容如下:</p><p><img src="https://s1.ax1x.com/2018/08/09/PyyuLD.png" alt="迁移文件内容"></p><p>Django框架根据我们设计的模型类生成了迁移文件,在迁移文件中我们可以看到fields列表中每一个元素跟BookInfo类属性名以及属性的类型是一致的。同时我们发现多了一个id项,这一项是Django框架帮我们自动生成的,在创建表的时候id就会作为对应表的主键列,并且主键列自动增长。</p><p>执行迁移命令如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py migrate</span></span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/08/09/Pyylod.png" alt="迁移后"></p><p>当执行迁移命令后,Django框架会读取迁移文件自动帮我们在数据库中生成对应的表格。</p><p>迁移后目录结构如下图:</p><p><img src="https://s1.ax1x.com/2018/08/09/PyyGWt.png" alt="迁移后"></p><p>Django默认采用sqlite3数据库,上图中的db.sqlite3就是Django框架帮我们自动生成的数据库文件。 sqlite3是一个很小的数据库,通常用在手机中,它跟mysql一样,我们也可以通过sql语句来操作它。</p><p>下面使用sqliteman打开db.sqlite3文件进行查看。如果没有安装sqliteman,需要先使用如下命令进行安装。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> apt-get install sqliteman</span></span><br></pre></td></tr></table></figure><p>安装成功之后,在终端输入sqliteman命令,敲击回车即可打开软件。</p><p><img src="https://s1.ax1x.com/2018/08/09/PyyDFs.png" alt="sqliteman"></p><p>细心会发现我们上面生成的表的名字叫做booktest_bookinfo,booktest是应用的名字,bookinfo是模型类的名字。</p><p>数据表的默认名称为:</p><blockquote><p><app_name>_<model_name></model_name></app_name></p></blockquote><h3 id="设计英雄类"><a href="#设计英雄类" class="headerlink" title="设计英雄类"></a>设计英雄类</h3><p>英雄类:</p><ul><li>类名:HeroInfo</li><li>英雄姓名:hname</li><li>英雄性别:hgender</li><li>英雄简介:hcomment</li><li>英雄所属图书:hbook</li><li>图书-英雄的关系为一对多</li></ul><p>打开booktest/models.py,定义英雄类代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HeroInfo</span><span class="params">(models.Model)</span>:</span></span><br><span class="line"> hname = models.CharField(max_length=<span class="number">20</span>)</span><br><span class="line"> hgender = models.BooleanField()</span><br><span class="line"> hcomment = models.CharField(max_length=<span class="number">100</span>)</span><br><span class="line"> hbook = models.ForeignKey(<span class="string">'BookInfo'</span>)</span><br></pre></td></tr></table></figure><p>这里要说明的是,BookInfo类和HeroInfo类之间具有一对多的关系,这个一对多的关系应该定义在多的那个类,也就是HeroInfo类中。</p><blockquote><p>hbook = models.ForeignKey(‘BookInfo’)这句代码就让BookInfo类和HeroInfo类之间建立了一对多的关系。</p></blockquote><p><strong>在我们之后迁移生成表的时候,Django框架就会自动帮我们在图书表和英雄表之间建立一个外键关系。</strong></p><p>生成迁移文件:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py makemigrations</span></span><br></pre></td></tr></table></figure><p>结果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/09/PyyX0e.png" alt="英雄迁移"></p><p>项目目录结构:</p><p><img src="https://s1.ax1x.com/2018/08/09/Pyyxkd.png" alt="项目目录"></p><p>执行迁移的命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py migrate</span></span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/08/09/Py6P6f.png" alt="迁移后"></p><p>最后我们可以看到数据库中生成的英雄表如下图:</p><p><img src="https://s1.ax1x.com/2018/08/09/Py6knS.png" alt="迁移sqlieman"></p><p>注意上图中booktest_heroinfo表中有一列hbook_id,这一列名为什么不叫hbook? hbook_id是根据HeroInfo类的关系属性hbook生成的,对应着图书表中的主键id。</p><h3 id="数据操作"><a href="#数据操作" class="headerlink" title="数据操作"></a>数据操作</h3><p>完成数据表的迁移之后,下面就可以通过进入项目的shell,进行简单的API操作。如果需要退出项目,可以使用ctrl+d快捷键或输入quit()。</p><p><strong>基础操作</strong></p><p>进入项目shell的命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py shell</span></span><br></pre></td></tr></table></figure><p>首先引入booktest/models中的类:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> from booktest.models import BookInfo,HeroInfo</span></span><br></pre></td></tr></table></figure><p>查询所有图书信息:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> BookInfo.objects.all()</span></span><br></pre></td></tr></table></figure><p>新建图书对象:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> b=BookInfo()</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.btitle=<span class="string">"射雕英雄传"</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> from datetime import date</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.bpub_date=date(1991,1,31)</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.save()</span></span><br></pre></td></tr></table></figure><p>再次查询所有图书信息:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ BookInfo.objects.all()</span><br><span class="line"> [<BookInfo: BookInfo object>]</span><br></pre></td></tr></table></figure><p>查找图书信息并查看值:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> b=BookInfo.objects.get(id=1)</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.id</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.btitle</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.bpub_date</span></span><br></pre></td></tr></table></figure><p>修改图书信息:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">b.bpub_date=date(2017,1,1)</span><br><span class="line">b.save()</span><br></pre></td></tr></table></figure><p>删除图书信息:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">b.delete()</span><br></pre></td></tr></table></figure><p><strong>对象的关联操作</strong></p><p>对于HeroInfo可以按照上面的方式进行增删改查操作。</p><p>创建一个BookInfo对象</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> b=BookInfo()</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.btitle=<span class="string">'abc'</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.bpub_date=date(2017,1,1)</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> b.save()</span></span><br></pre></td></tr></table></figure><p>创建一个HeroInfo对象</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> h=HeroInfo()</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> h.hname=<span class="string">'a1'</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> h.hgender=False</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> h.hcomment=<span class="string">'he is a boy'</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> h.hbook=b</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> h.save()</span></span><br></pre></td></tr></table></figure><p>图书与英雄是一对多的关系,django中提供了关联的操作方式。</p><p>获得关联集合:返回当前book对象的所有hero。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> b.heroinfo_set.all()</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> h.hbook</span></span><br></pre></td></tr></table></figure><h2 id="后台管理"><a href="#后台管理" class="headerlink" title="后台管理"></a>后台管理</h2><blockquote><p>Django能够根据定义的模型类自动地生成管理页面。 所以我们可以设计一个页面,通过对这个页面的操作来实现对新闻数据库的增删改查操作。 <strong>这就是Django的后台管理</strong></p></blockquote><p>使用Django的管理模块,需要按照如下步骤操作:</p><ul><li>1.管理界面本地化</li><li>2.创建管理员</li><li>3.注册模型类</li><li>4.自定义管理页面</li></ul><h3 id="管理界面的本地化"><a href="#管理界面的本地化" class="headerlink" title="管理界面的本地化"></a>管理界面的本地化</h3><p>本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化,中国大陆地区使用简体中文,时区使用亚洲/上海时区,注意这里不使用北京时区表示。</p><p>打开test1/settings.py文件,找到语言编码、时区的设置项,将内容改为如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> vim test1/settings.py</span></span><br><span class="line">LANGUAGE_CODE = 'zh-hans' #使用中国语言</span><br><span class="line">TIME_ZONE = 'Asia/Shanghai' #使用中国上海时间</span><br></pre></td></tr></table></figure><h3 id="创建管理员"><a href="#创建管理员" class="headerlink" title="创建管理员"></a>创建管理员</h3><p>创建管理员的命令如下,按提示输入用户名、邮箱、密码。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py createsuperuser</span></span><br></pre></td></tr></table></figure><p>接下来启动服务器。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> python manage.py runserver</span></span><br></pre></td></tr></table></figure><p>打开浏览器,在地址栏中输入如下地址后回车。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/admin/</span><br></pre></td></tr></table></figure><p>登录成功后界面如下,但是并没有图书、英雄的管理入口,接下来进行第三步操作。</p><p><img src="https://s1.ax1x.com/2018/08/09/Py6DBD.png" alt="登录成功"></p><h3 id="注册模型类"><a href="#注册模型类" class="headerlink" title="注册模型类"></a>注册模型类</h3><p>登录后台管理后,默认没有我们创建的应用中定义的模型类,需要在自己应用中的admin.py文件中注册,才可以在后台管理中看到,并进行增删改查操作。</p><p>打开booktest/admin.py文件,编写如下代码:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.contrib <span class="keyword">import</span> admin</span><br><span class="line"><span class="keyword">from</span> booktest.models <span class="keyword">import</span> BookInfo,HeroInfo</span><br><span class="line"></span><br><span class="line">admin.site.register(BookInfo)</span><br><span class="line">admin.site.register(HeroInfo)</span><br></pre></td></tr></table></figure><p>到浏览器中刷新页面,可以看到模型类BookInfo和HeroInfo的管理了。</p><h3 id="自定义管理页面"><a href="#自定义管理页面" class="headerlink" title="自定义管理页面"></a>自定义管理页面</h3><p>在列表页只显示出了BookInfo object,对象的其它属性并没有列出来,查看非常不方便。 Django提供了自定义管理页面的功能,比如列表页要显示哪些值。</p><p>打开booktest/admin.py文件,自定义类,继承自admin.ModelAdmin类。</p><ul><li>属性list_display表示要显示哪些属性</li><li><p>修改模型类BookInfo的注册代码如下</p></li><li><p>最终booktest/admin.py文件代码如下</p></li></ul><p>最终自定义如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.contrib <span class="keyword">import</span> admin</span><br><span class="line"><span class="keyword">from</span> booktest.models <span class="keyword">import</span> BookInfo,HeroInfo</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookInfoAdmin</span><span class="params">(admin.ModelAdmin)</span>:</span></span><br><span class="line"> list_display = [<span class="string">'id'</span>, <span class="string">'btitle'</span>, <span class="string">'bpub_date'</span>]</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HeroInfoAdmin</span><span class="params">(admin.ModelAdmin)</span>:</span></span><br><span class="line"> list_display = [<span class="string">'id'</span>, <span class="string">'hname'</span>,<span class="string">'hgender'</span>,<span class="string">'hcomment'</span>]</span><br><span class="line"></span><br><span class="line">admin.site.register(BookInfo,BookInfoAdmin)</span><br><span class="line">admin.site.register(HeroInfo,HeroInfoAdmin)</span><br></pre></td></tr></table></figure><h2 id="视图及URL"><a href="#视图及URL" class="headerlink" title="视图及URL"></a>视图及URL</h2><blockquote><p>后台管理页面做好了,接下来就要做公共访问的页面了。当我们刚刚在浏览器中输入 <a href="http://127.0.0.1:8000/admin/" target="_blank" rel="noopener">http://127.0.0.1:8000/admin/</a> 之后,浏览器显示出了后台管理的登录页面,那有没有同学想过这个服务器是怎么给我们找到这个页面并返回呢?/admin/是我们想要请求的页面,服务器在收到这个请求之后,就一定对应着一个处理动作,这个处理动作就是帮我们产生页面内容并返回回来,这个过程是由<strong>视图</strong>来做的。</p></blockquote><p>对于django的设计框架MVT,用户在URL中请求的是视图,视图接收请求后进行处理,并将处理的结果返回给请求者。</p><p>使用视图时需要进行两步操作:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">* 1.定义视图函数</span><br><span class="line">* 2.配置URLconf</span><br></pre></td></tr></table></figure><h3 id="定义视图函数"><a href="#定义视图函数" class="headerlink" title="定义视图函数"></a>定义视图函数</h3><p>视图就是一个Python函数,被定义在views.py中。视图的必须有一个参数,一般叫request,视图必须返回HttpResponse对象,HttpResponse中的参数内容会显示在浏览器的页面上。打开booktest/views.py文件,定义视图index如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.http <span class="keyword">import</span> HttpResponse</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(<span class="string">"index"</span>)</span><br></pre></td></tr></table></figure><h3 id="配置URLconf"><a href="#配置URLconf" class="headerlink" title="配置URLconf"></a>配置URLconf</h3><p>请求者在浏览器地址栏中输入url,请求到网站后,获取url信息,然后与编写好的URLconf逐条匹配,如果匹配成功则调用对应的视图函数,如果所有的URLconf都没有匹配成功,则返回404错误。</p><p>一条URLconf包括url规则、视图两部分:</p><ul><li>url规则使用正则表达式定义。</li><li>视图就是在views.py中定义的视图函数。</li></ul><p>需要两步完成URLconf配置:</p><ul><li>1.在应用中定义URLconf</li><li>2.包含到项目的URLconf中</li></ul><p>在booktest/应用下创建urls.py文件,定义代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url</span><br><span class="line"><span class="keyword">from</span> booktest <span class="keyword">import</span> views</span><br><span class="line">urlpatterns = [</span><br><span class="line"> url(<span class="string">r'^$'</span>, views.index),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>包含到项目中:打开test1/urls.py文件,为urlpatterns列表增加项如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">url(<span class="string">r'^'</span>, include(<span class="string">'booktest.urls'</span>)),</span><br></pre></td></tr></table></figure><p>test1/urls.py文件完整代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">from django.conf.urls import include, url</span><br><span class="line">from django.contrib import admin</span><br><span class="line"></span><br><span class="line">urlpatterns = [</span><br><span class="line"> url(r'^admin/', include(admin.site.urls)),</span><br><span class="line"> url(r'^', include('booktest.urls')),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p>视图和URLconf都定义好了,接下来在浏览器地址栏中输入网址:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://127.0.0.1:8000/</span><br></pre></td></tr></table></figure><p>网页显示效果如下图,视图被成功执行了。</p><p><img src="https://s1.ax1x.com/2018/08/10/P69o4g.png" alt="首页"></p><h2 id="模板"><a href="#模板" class="headerlink" title="模板"></a>模板</h2><h3 id="为什么使用模版?"><a href="#为什么使用模版?" class="headerlink" title="为什么使用模版?"></a>为什么使用模版?</h3><p><strong>如何向请求者返回一个漂亮的页面呢?</strong></p><p>肯定需要用到html、css,如果想要更炫的效果还要加入js,问题来了,这么一堆字段串全都写到视图中,作为HttpResponse()的参数吗?这样定义就太麻烦了吧,因为定义字符串是不会出任何效果和错误的,如果有一个专门定义前端页面的地方就好了。</p><p>解决问题的技术来了:<strong>模板</strong>。</p><p>在Django中,将前端的内容定义在模板中,然后再把模板交给视图调用,各种漂亮、炫酷的效果就出现了。</p><h3 id="创建模板"><a href="#创建模板" class="headerlink" title="创建模板"></a>创建模板</h3><p>为应用booktest下的视图index创建模板index.html,目录结构如下图:</p><p><img src="https://s1.ax1x.com/2018/08/10/P69bgs.png" alt="创建模板"></p><p>设置查找模板的路径:打开test1/settings.py文件,设置TEMPLATES的DIRS值</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'DIRS'</span>: [os.path.join(BASE_DIR, <span class="string">'templates'</span>)],</span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/08/10/P69qvn.png" alt="模板地址"></p><h3 id="定义模板"><a href="#定义模板" class="headerlink" title="定义模板"></a>定义模板</h3><p>打开templtes/booktest/index.html文件,定义代码如下:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><html></span><br><span class="line"><head></span><br><span class="line"> <title>图书列表</title></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line"><h1>{{title}}</h1></span><br><span class="line">{%<span class="keyword">for</span> i <span class="keyword">in</span> list%}</span><br><span class="line">{{i}}<br></span><br><span class="line">{%endfor%}</span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><p>在模板中输出变量语法如下,变量可能是从视图中传递过来的,也可能是在模板中定义的。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{{变量名}}</span><br></pre></td></tr></table></figure><p>在模板中编写代码段语法如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">{%代码段%}</span><br></pre></td></tr></table></figure><h3 id="视图调用模板"><a href="#视图调用模板" class="headerlink" title="视图调用模板"></a>视图调用模板</h3><p>调用模板分为三步骤:</p><ul><li>1.找到模板</li><li>2.定义上下文</li><li>3.渲染模板</li></ul><p>打开booktst/views.py文件,调用上面定义的模板文件</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.http <span class="keyword">import</span> HttpResponse</span><br><span class="line"><span class="keyword">from</span> django.template <span class="keyword">import</span> loader,RequestContext</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> <span class="comment"># 1.获取模板</span></span><br><span class="line"> template=loader.get_template(<span class="string">'booktest/index.html'</span>)</span><br><span class="line"> <span class="comment"># 2.定义上下文</span></span><br><span class="line"> context=RequestContext(request,{<span class="string">'title'</span>:<span class="string">'图书列表'</span>,<span class="string">'list'</span>:range(<span class="number">10</span>)})</span><br><span class="line"> <span class="comment"># 3.渲染模板</span></span><br><span class="line"> <span class="keyword">return</span> HttpResponse(template.render(context))</span><br></pre></td></tr></table></figure><p>打开浏览器刷新页面,显示效果如下图:</p><p><img src="https://s1.ax1x.com/2018/08/10/P69jbV.png" alt="图书列表"></p><h3 id="视图调用模板简写"><a href="#视图调用模板简写" class="headerlink" title="视图调用模板简写"></a>视图调用模板简写</h3><p>视图调用模板都要执行以上三部分,于是Django提供了一个函数render封装了以上代码。 方法render包含3个参数:</p><ul><li>第一个参数为request对象</li><li>第二个参数为模板文件路径</li><li>第三个参数为字典,表示向模板中传递的上下文数据</li></ul><p>打开booktst/views.py文件,调用render的代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> render</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(request)</span>:</span></span><br><span class="line"> context={<span class="string">'title'</span>:<span class="string">'图书列表'</span>,<span class="string">'list'</span>:range(<span class="number">10</span>)}</span><br><span class="line"> <span class="keyword">return</span> render(request,<span class="string">'booktest/index.html'</span>,context)</span><br></pre></td></tr></table></figure><h2 id="完成小项目"><a href="#完成小项目" class="headerlink" title="完成小项目"></a>完成小项目</h2><p>现在还需要的代码包括三个方面,三个方面顺序不分先后。</p><ul><li>1.定义视图</li><li>2.定义URLconf</li><li>3.定义模板</li></ul><h3 id="定义视图"><a href="#定义视图" class="headerlink" title="定义视图"></a>定义视图</h3><p>编写booktest/views.py文件如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.shortcuts <span class="keyword">import</span> render</span><br><span class="line"><span class="keyword">from</span> booktest.models <span class="keyword">import</span> BookInfo</span><br><span class="line"></span><br><span class="line"><span class="comment">#首页,展示所有图书</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">(reqeust)</span>:</span></span><br><span class="line"> <span class="comment">#查询所有图书</span></span><br><span class="line"> booklist = BookInfo.objects.all()</span><br><span class="line"> <span class="comment">#将图书列表传递到模板中,然后渲染模板</span></span><br><span class="line"> <span class="keyword">return</span> render(reqeust, <span class="string">'booktest/index.html'</span>, {<span class="string">'booklist'</span>: booklist})</span><br><span class="line"></span><br><span class="line"><span class="comment">#详细页,接收图书的编号,根据编号查询,再通过关系找到本图书的所有英雄并展示</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">detail</span><span class="params">(reqeust, bid)</span>:</span></span><br><span class="line"> <span class="comment">#根据图书编号对应图书</span></span><br><span class="line"> book = BookInfo.objects.get(id=int(bid))</span><br><span class="line"> <span class="comment">#查找book图书中的所有英雄信息</span></span><br><span class="line"> heros = book.heroinfo_set.all()</span><br><span class="line"> <span class="comment">#将图书信息传递到模板中,然后渲染模板</span></span><br><span class="line"> <span class="keyword">return</span> render(reqeust, <span class="string">'booktest/detail.html'</span>, {<span class="string">'book'</span>:book,<span class="string">'heros'</span>:heros})</span><br></pre></td></tr></table></figure><h3 id="定义URLconf"><a href="#定义URLconf" class="headerlink" title="定义URLconf"></a>定义URLconf</h3><p>编写booktest/urls.py文件如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf.urls <span class="keyword">import</span> url</span><br><span class="line"><span class="comment">#引入视图模块</span></span><br><span class="line"><span class="keyword">from</span> booktest <span class="keyword">import</span> views</span><br><span class="line">urlpatterns = [</span><br><span class="line"> <span class="comment">#配置首页url</span></span><br><span class="line"> url(<span class="string">r'^$'</span>, views.index),</span><br><span class="line"> <span class="comment">#配置详细页url,\d+表示多个数字,小括号用于取值,建议复习下正则表达式</span></span><br><span class="line"> url(<span class="string">r'^(\d+)/$'</span>,views.detail),</span><br><span class="line">]</span><br></pre></td></tr></table></figure><h3 id="定义模板-1"><a href="#定义模板-1" class="headerlink" title="定义模板"></a>定义模板</h3><p>编写templates/booktest/index.html文件如下:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><html></span><br><span class="line"><head></span><br><span class="line"> <title>首页</title></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line"><h1>图书列表</h1></span><br><span class="line"><ul></span><br><span class="line"> {<span class="comment">#遍历图书列表#}</span></span><br><span class="line"> {%<span class="keyword">for</span> book <span class="keyword">in</span> booklist%}</span><br><span class="line"> <li></span><br><span class="line"> {<span class="comment">#输出图书名称,并设置超链接,链接地址是一个数字#}</span></span><br><span class="line"> <a href="/{{book.id}}/">{{book.btitle}}</a></span><br><span class="line"> </li></span><br><span class="line"> {%endfor%}</span><br><span class="line"></ul></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><p>编写templates/booktest/detail.html文件如下:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><html></span><br><span class="line"><head></span><br><span class="line"> <title>详细页</title></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line">{<span class="comment">#输出图书标题#}</span></span><br><span class="line"><h1>{{book.btitle}}</h1></span><br><span class="line"><ul></span><br><span class="line"> {<span class="comment">#通过关系找到本图书的所有英雄,并遍历#}</span></span><br><span class="line"> {%<span class="keyword">for</span> hero <span class="keyword">in</span> heros%}</span><br><span class="line"> {<span class="comment">#输出英雄的姓名及描述#}</span></span><br><span class="line"> <li>{{hero.hname}}---{{hero.hcomment}}</li></span><br><span class="line"> {%endfor%}</span><br><span class="line"></ul></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><h3 id="项目效果"><a href="#项目效果" class="headerlink" title="项目效果"></a>项目效果</h3><p><strong>首页:</strong></p><p><img src="https://s1.ax1x.com/2018/08/10/P6Cd2j.png" alt="首页"></p><p><strong>详情页:</strong></p><p><img src="https://s1.ax1x.com/2018/08/10/P6CeUO.png" alt="详情页"></p>]]></content>
<summary type="html">
<h2 id="认识Django"><a href="#认识Django" class="headerlink" title="认识Django"></a>认识Django</h2><h3 id="Django简介"><a href="#Django简介" class="headerlink" title="Django简介"></a>Django简介</h3><p>Django,发音为[`dʒæŋɡəʊ],是用python语言写的开源web开发框架,并遵循MVC设计。劳伦斯出版集团为了开发以新闻内容为主的网站,而开发出来了这个框架,于2005年7月在BSD许可证下发布。这个名称来源于比利时的爵士音乐家DjangoReinhardt,他是一个吉普赛人,主要以演奏吉它为主,还演奏过小提琴等。由于Django在近年来的迅速发展,应用越来越广泛,被著名IT开发杂志SDTimes评选为2013SDTimes100,位列”API、库和框架”分类第6位,被认为是该领域的佼佼者。Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以”插件”形式服务于整个框架,Django有许多功能强大的第三方插件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展性。它还强调快速开发和DRY(DoNotRepeatYourself)原则。</p>
<blockquote>
<p>点击查看<a href="https://www.djangoproject.com/" target="_blank" rel="noopener">django官方网站</a></p>
<p>点击查看<a href="https://github.com/django/django" target="_blank" rel="noopener">django源码</a></p>
<p>点击查看<a href="https://yiyibooks.cn/xx/django_182/index.html" target="_blank" rel="noopener">1.8.2官方中文文档</a></p>
</blockquote>
<h3 id="MVC简介"><a href="#MVC简介" class="headerlink" title="MVC简介"></a>MVC简介</h3><p>MVC的全拼为Model-View-Controller,最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式,是为了将传统的输入(input)、处理(processing)、输出(output)任务运用到图形化用户交互模型中而设计的。随着标准输入输出设备的出现,开发人员只需要将精力集中在业务逻辑的分析与实现上。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。现在虽然不再使用原来的分工方式,但是这种<strong>分工的思想</strong>被沿用下来,广泛应用于软件工程中,是一种典型并且应用广泛的软件架构模式。后来,MVC的思想被应用在了Web开发方面,被称为Web MVC框架。</p>
<p>MVC框架的核心思想是:<strong>解耦</strong>,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。当前主流的开发语言如Java、PHP、Python中都有MVC框架。</p>
<h3 id="Web-MVC各部分的功能"><a href="#Web-MVC各部分的功能" class="headerlink" title="Web MVC各部分的功能"></a>Web MVC各部分的功能</h3><ul>
<li>M全拼为Model,主要封装对数据库层的访问,对数据库中的数据进行增、删、改、查操作。</li>
<li>V全拼为View,用于封装结果,生成页面展示的html内容。</li>
<li>C全拼为Controller,用于接收请求,处理业务逻辑,与Model和View交互,返回结果。</li>
</ul>
<p><img src="https://s1.ax1x.com/2018/08/09/PyriXF.png" alt="mvc"></p>
<h3 id="MVT各部分的功能"><a href="#MVT各部分的功能" class="headerlink" title="MVT各部分的功能"></a>MVT各部分的功能</h3><p>Django框架遵循MVC设计,并且有一个专有名词:MVT</p>
<ul>
<li>M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。</li>
<li>V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。</li>
<li>T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。</li>
</ul>
<p><img src="https://s1.ax1x.com/2018/08/09/PyrA0J.png" alt="mvt"></p>
</summary>
<category term="Django入门" scheme="http://www.chenfanlinux.org/categories/Django%E5%85%A5%E9%97%A8/"/>
<category term="Django" scheme="http://www.chenfanlinux.org/tags/Django/"/>
</entry>
<entry>
<title>Python网络编程-tcp</title>
<link href="http://www.chenfanlinux.org/2018/06/22/Python%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B-tcp/"/>
<id>http://www.chenfanlinux.org/2018/06/22/Python网络编程-tcp/</id>
<published>2018-06-22T08:43:44.000Z</published>
<updated>2018-06-22T08:44:51.000Z</updated>
<content type="html"><![CDATA[<h2 id="TCP简介"><a href="#TCP简介" class="headerlink" title="TCP简介"></a>TCP简介</h2><h3 id="TCP介绍"><a href="#TCP介绍" class="headerlink" title="TCP介绍"></a>TCP介绍</h3><p><strong>TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为TCP)</strong>是一种面向连接的、可靠的、基于字节流的传输层通信协议 。TCP通信需要经过<strong>创建连接、数据传送、终止连接</strong>三个步骤。TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,”打电话”” 。</p><h3 id="TCP特点"><a href="#TCP特点" class="headerlink" title="TCP特点"></a>TCP特点</h3><h4 id="1-面向连接"><a href="#1-面向连接" class="headerlink" title="1. 面向连接"></a>1. 面向连接</h4><p>通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。双方间的数据传输都可以通过这一个连接进行。完成数据交换后,双方必须断开此连接,以释放系统资源。<strong>这种连接是一对一的,因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。</strong></p><h4 id="2-可靠传输"><a href="#2-可靠传输" class="headerlink" title="2. 可靠传输"></a>2. 可靠传输</h4><p>1)<strong>TCP采用发送应答机制</strong></p><p>TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功</p><p>2)<strong>超时重传</strong></p><p>发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。</p><p>TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。</p><p>3)<strong>错误校验</strong></p><p>TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。</p><p>4) <strong>流量控制和阻塞管理</strong></p><p>流量控制用来避免主机发送得过快而使接收方来不及完全收下。</p><a id="more"></a><h3 id="TCP和UDP的不同"><a href="#TCP和UDP的不同" class="headerlink" title="TCP和UDP的不同"></a>TCP和UDP的不同</h3><ul><li>面向连接(确认有创建三方交握,连接已创建才作传输。)</li><li>有序数据传输</li><li>重发丢失的数据包</li><li>舍弃重复的数据包</li><li>无差错的数据传输</li><li>阻塞/流量控制</li></ul><h4 id="UDP通信模型"><a href="#UDP通信模型" class="headerlink" title="UDP通信模型"></a>UDP通信模型</h4><p>udp通信模型中,在通信开始之前,不需要建立相关的链接,只需要发送数据即可,类似于生活中,”写信”” 。</p><p><img src="https://s1.ax1x.com/2018/06/22/PSzWFS.png" alt=""></p><h4 id="TCP通信模型"><a href="#TCP通信模型" class="headerlink" title="TCP通信模型"></a>TCP通信模型</h4><p>tcp通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,”打电话””</p><p><img src="https://s1.ax1x.com/2018/06/22/PpeI4s.png" alt=""></p><h3 id="TCP的三次握手和四次挥手"><a href="#TCP的三次握手和四次挥手" class="headerlink" title="TCP的三次握手和四次挥手"></a>TCP的三次握手和四次挥手</h3><h4 id="三次握手"><a href="#三次握手" class="headerlink" title="三次握手"></a>三次握手</h4><p><img src="https://s1.ax1x.com/2018/06/22/PpevE4.png" alt=""></p><h4 id="四次挥手"><a href="#四次挥手" class="headerlink" title="四次挥手"></a>四次挥手</h4><p><img src="https://s1.ax1x.com/2018/06/22/PpexUJ.png" alt=""></p><h2 id="TCP客户端"><a href="#TCP客户端" class="headerlink" title="TCP客户端"></a>TCP客户端</h2><p>所谓的服务器端:就是提供服务的一方,而客户端,就是需要被服务的一方</p><h3 id="tcp客户端构建流程"><a href="#tcp客户端构建流程" class="headerlink" title="tcp客户端构建流程"></a>tcp客户端构建流程</h3><p>tcp的客户端要比服务器端简单很多,如果说服务器端是需要自己买手机、查手机卡、设置铃声、等待别人打电话流程的话,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多 。</p><p>代码:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建socket</span></span><br><span class="line">tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 目的信息</span></span><br><span class="line">server_ip = input(<span class="string">"请输入服务器ip:"</span>)</span><br><span class="line">server_port = int(input(<span class="string">"请输入服务器port:"</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 链接服务器</span></span><br><span class="line">tcp_client_socket.connect((server_ip, server_port))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提示用户输入数据</span></span><br><span class="line">send_data = input(<span class="string">"请输入要发送的数据:"</span>)</span><br><span class="line"></span><br><span class="line">tcp_client_socket.send(send_data.encode(<span class="string">"utf8"</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 接收对方发送过来的数据,最大接收1024个字节</span></span><br><span class="line">recvData = tcp_client_socket.recv(<span class="number">1024</span>)</span><br><span class="line">print(<span class="string">'接收到的数据为:'</span>, recvData.decode(<span class="string">'gbk'</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭套接字</span></span><br><span class="line">tcp_client_socket.close()</span><br></pre></td></tr></table></figure><h3 id="运行流程"><a href="#运行流程" class="headerlink" title="运行流程"></a>运行流程</h3><p>tcp脚本客户端:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># python 01-tcp_client.py</span></span><br><span class="line">请输入服务器ip:192.168.30.71</span><br><span class="line">请输入服务器port:8080</span><br><span class="line">请输入要发送的数据:你好,我是tcp客户端!</span><br><span class="line">接收到的数据为: 好的,我知道了</span><br></pre></td></tr></table></figure><p>windows网络调试助手:</p><p><img src="https://s1.ax1x.com/2018/06/22/PpmGVg.png" alt=""></p><h2 id="TCP服务端"><a href="#TCP服务端" class="headerlink" title="TCP服务端"></a>TCP服务端</h2><h3 id="生活中的电话机"><a href="#生活中的电话机" class="headerlink" title="生活中的电话机"></a>生活中的电话机</h3><p>如果想让别人能更够打通咱们的电话获取相应服务的话,需要做以下几件事情:</p><ol><li>买个手机</li><li>插上手机卡</li><li>设计手机为正常接听状态(即能够响铃)</li><li>静静的等着别人拨打</li></ol><h3 id="tcp服务器"><a href="#tcp服务器" class="headerlink" title="tcp服务器"></a>tcp服务器</h3><p>如同上面的电话机过程一样,在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下:</p><ol><li>socket创建一个套接字</li><li>bind绑定ip和port</li><li>listen使套接字变为可以被动链接</li><li>accept等待客户端的链接</li><li>recv/send接收发送数据</li></ol><h3 id="服务端代码"><a href="#服务端代码" class="headerlink" title="服务端代码"></a>服务端代码</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding:utf8 _*_</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建tcp socket</span></span><br><span class="line">tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 本地信息</span></span><br><span class="line">address = (<span class="string">""</span>, <span class="number">7788</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 绑定本地信息</span></span><br><span class="line">tcp_server_socket.bind(address)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了</span></span><br><span class="line">tcp_server_socket.listen(<span class="number">128</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务</span></span><br><span class="line"><span class="comment"># client_socket用来为这个客户端服务</span></span><br><span class="line"><span class="comment"># tcp_server_socket就可以省下来专门等待其他新客户端的链接</span></span><br><span class="line">client_socket, clientAddr = tcp_server_socket.accept()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 接收对方发送过来的数据</span></span><br><span class="line">recv_data = client_socket.recv(<span class="number">1024</span>) <span class="comment"># 接收1024个字节</span></span><br><span class="line">print(<span class="string">'接收到的数据为:'</span>, recv_data.decode(<span class="string">'gbk'</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 发送一些数据到客户端</span></span><br><span class="line">client_socket.send(<span class="string">"thank you !"</span>.encode(<span class="string">'utf-8'</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接</span></span><br><span class="line">client_socket.close()</span><br></pre></td></tr></table></figure><h3 id="运行流程-1"><a href="#运行流程-1" class="headerlink" title="运行流程"></a>运行流程</h3><p>tcp服务端收到的数据:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># python 02-tcp_server.py</span></span><br><span class="line">接收到的数据为: www.chenfanlinux.org很不错</span><br></pre></td></tr></table></figure><p>windows网络助手:</p><p><img src="https://s1.ax1x.com/2018/06/22/PpnPij.png" alt=""></p><h3 id="tcp注意点"><a href="#tcp注意点" class="headerlink" title="tcp注意点"></a>tcp注意点</h3><ol><li>tcp服务器一般情况下都需要绑定,否则客户端找不到这个服务器</li><li>tcp客户端一般不绑定,因为是主动链接服务器,所以只要确定好服务器的ip、port等信息就好,本地客户端可以随机</li><li>tcp服务器中通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的</li><li>当客户端需要链接服务器时,就需要使用connect进行链接,udp是不需要链接的而是直接发送,但是tcp必须先链接,只有链接成功才能通信</li><li>当一个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务</li><li>listen后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的</li><li>关闭listen后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信</li><li>关闭accept返回的套接字意味着这个客户端已经服务完毕</li><li>当客户端的套接字调用close后,服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线</li></ol><h2 id="案例:文件下载器"><a href="#案例:文件下载器" class="headerlink" title="案例:文件下载器"></a>案例:文件下载器</h2><p><strong>服务端代码:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取文件的内容</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_file_content</span><span class="params">(file_name)</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> <span class="keyword">with</span> open(file_name, <span class="string">'rb'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> file_content = f.read()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> file_content</span><br><span class="line"></span><br><span class="line"> <span class="keyword">except</span> Exception:</span><br><span class="line"> print(<span class="string">"没有下载的文件:%s"</span> % file_name)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">if</span> len(sys.argv) != <span class="number">2</span>:</span><br><span class="line"> print(<span class="string">"请按照如下方式运行:python xxx.py 7890"</span>)</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="comment"># 运行方式为python xxx.py 7890</span></span><br><span class="line"> <span class="comment"># 获取端口号</span></span><br><span class="line"> port = int(sys.argv[<span class="number">1</span>])</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 创建socket</span></span><br><span class="line"> tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 本地信息</span></span><br><span class="line"> address = (<span class="string">''</span>, port)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 绑定本地信息</span></span><br><span class="line"> tcp_server_socket.bind(address)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 将主动套接字变为被动套接字</span></span><br><span class="line"> tcp_server_socket.listen(<span class="number">128</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line"> <span class="comment"># 等待客户端的链接,即为这个客户端发送文件</span></span><br><span class="line"> client_socket, clientAddr = tcp_server_socket.accept()</span><br><span class="line"> <span class="comment"># 接收对方发送过来的数据</span></span><br><span class="line"> recv_data = client_socket.recv(<span class="number">1024</span>) <span class="comment"># 接收1024个字节</span></span><br><span class="line"> file_name = recv_data.decode(<span class="string">"utf-8"</span>)</span><br><span class="line"> print(<span class="string">"对方请求下载的文件名为:%s"</span> % file_name)</span><br><span class="line"> file_content = get_file_content(file_name)</span><br><span class="line"> <span class="comment"># 发送文件的数据给客户端</span></span><br><span class="line"> <span class="comment"># 因为获取打开文件时是以rb方式打开,所以file_content中的数据已经是二进制的格式,因此不需要encode编码</span></span><br><span class="line"> <span class="keyword">if</span> file_content:</span><br><span class="line"> client_socket.send(file_content)</span><br><span class="line"> <span class="comment"># 关闭这个套接字</span></span><br><span class="line"> client_socket.close()</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 关闭监听套接字</span></span><br><span class="line"> tcp_server_socket.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure><p><strong>客户端代码:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> socket <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 创建socket</span></span><br><span class="line"> tcp_client_socket = socket(AF_INET, SOCK_STREAM)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 目的信息</span></span><br><span class="line"> server_ip = input(<span class="string">"请输入服务器ip:"</span>)</span><br><span class="line"> server_port = int(input(<span class="string">"请输入服务器port:"</span>))</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 链接服务器</span></span><br><span class="line"> tcp_client_socket.connect((server_ip, server_port))</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 输入需要下载的文件名</span></span><br><span class="line"> file_name = input(<span class="string">"请输入要下载的文件名:"</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 发送文件下载请求</span></span><br><span class="line"> tcp_client_socket.send(file_name.encode(<span class="string">"utf-8"</span>))</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 接收对方发送过来的数据,最大接收1024个字节(1K)</span></span><br><span class="line"> recv_data = tcp_client_socket.recv(<span class="number">1024</span>)</span><br><span class="line"> <span class="comment"># print('接收到的数据为:', recv_data.decode('utf-8'))</span></span><br><span class="line"> <span class="comment"># 如果接收到数据再创建文件,否则不创建</span></span><br><span class="line"> <span class="keyword">if</span> recv_data:</span><br><span class="line"> <span class="keyword">with</span> open(<span class="string">"[接收]"</span>+file_name, <span class="string">"wb"</span>) <span class="keyword">as</span> f:</span><br><span class="line"> f.write(recv_data)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 关闭套接字</span></span><br><span class="line"> tcp_client_socket.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="TCP简介"><a href="#TCP简介" class="headerlink" title="TCP简介"></a>TCP简介</h2><h3 id="TCP介绍"><a href="#TCP介绍" class="headerlink" title="TCP介绍"></a>TCP介绍</h3><p><strong>TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为TCP)</strong>是一种面向连接的、可靠的、基于字节流的传输层通信协议 。TCP通信需要经过<strong>创建连接、数据传送、终止连接</strong>三个步骤。TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据,类似于生活中,”打电话”” 。</p>
<h3 id="TCP特点"><a href="#TCP特点" class="headerlink" title="TCP特点"></a>TCP特点</h3><h4 id="1-面向连接"><a href="#1-面向连接" class="headerlink" title="1. 面向连接"></a>1. 面向连接</h4><p>通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。双方间的数据传输都可以通过这一个连接进行。完成数据交换后,双方必须断开此连接,以释放系统资源。<strong>这种连接是一对一的,因此TCP不适用于广播的应用程序,基于广播的应用程序请使用UDP协议。</strong></p>
<h4 id="2-可靠传输"><a href="#2-可靠传输" class="headerlink" title="2. 可靠传输"></a>2. 可靠传输</h4><p>1)<strong>TCP采用发送应答机制</strong></p>
<p>TCP发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功</p>
<p>2)<strong>超时重传</strong></p>
<p>发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。</p>
<p>TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。</p>
<p>3)<strong>错误校验</strong></p>
<p>TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。</p>
<p>4) <strong>流量控制和阻塞管理</strong></p>
<p>流量控制用来避免主机发送得过快而使接收方来不及完全收下。</p>
</summary>
<category term="Python网络编程" scheme="http://www.chenfanlinux.org/categories/Python%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/"/>
<category term="tcp网络编程" scheme="http://www.chenfanlinux.org/tags/tcp%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>Python网络编程-udp</title>
<link href="http://www.chenfanlinux.org/2018/06/22/Python%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B-udp/"/>
<id>http://www.chenfanlinux.org/2018/06/22/Python网络编程-udp/</id>
<published>2018-06-22T03:46:03.000Z</published>
<updated>2018-06-22T03:47:36.000Z</updated>
<content type="html"><![CDATA[<h2 id="网络编程中的重要概念"><a href="#网络编程中的重要概念" class="headerlink" title="网络编程中的重要概念"></a>网络编程中的重要概念</h2><blockquote><p>所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信。</p></blockquote><h3 id="网络"><a href="#网络" class="headerlink" title="网络"></a>网络</h3><ul><li>使用网络能够把多方链接在一起,然后可以进行数据传递</li><li>所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信</li></ul><h3 id="ip地址"><a href="#ip地址" class="headerlink" title="ip地址"></a>ip地址</h3><p><strong>用来在网络中标记一台电脑,比如192.168.1.1;在本地局域网上是唯一的。每一个IP地址包括两部分:网络地址和主机地址。</strong></p><ul><li><p>一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”,</p><p>地址范围1.0.0.1-126.255.255.254。</p></li><li><p>一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,</p><p>地址范围128.1.0.1-191.255.255.254。</p></li><li><p>一个C类IP地址由3字节的网络地址和1字节的主机地址组成,网络地址的最高位必须是“110”</p><p>范围192.0.1.1-223.255.255.254。</p></li><li><p>D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。</p></li><li><p>E类地址保留,仅作实验和开发用 。</p></li><li><p>在这么多网络IP中,国际规定有一部分IP地址是用于我们的局域网使用,也就</p><p>是属于私网IP。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 私网ip的地址</span></span><br><span class="line">10.0.0.0~10.255.255.255</span><br><span class="line">172.16.0.0~172.31.255.255</span><br><span class="line">192.168.0.0~192.168.255.255</span><br></pre></td></tr></table></figure></li></ul><a id="more"></a><h3 id="端口"><a href="#端口" class="headerlink" title="端口"></a>端口</h3><blockquote><p>如果一个程序需要收发网络数据,那么就需要有这样的端口,在linux系统中,端口可以有65536(2的16次方)个之多!既然有这么多,操作系统为了统一管理,所以进行了编号,这就是<code>端口号</code> 。</p></blockquote><h4 id="端口分类"><a href="#端口分类" class="headerlink" title="端口分类"></a>端口分类</h4><ul><li>知名端口:知名端口是众所周知的端口号,范围从0到1023 。一般情况下,如果一个程序需要使用知名端口的需要有root权限 。</li><li>动态端口:动态端口的范围是从1024到65535 。动态分配是指当一个系统程序或应用程序程序需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。当这个程序关闭时,同时也就释放了所占用的端口号。</li></ul><h4 id="怎样查看端口?"><a href="#怎样查看端口?" class="headerlink" title="怎样查看端口?"></a>怎样查看端口?</h4><ul><li>用<code>netstat -tnlp</code>查看端口状态</li><li><code>lsof -i [tcp/udp]:2425</code> 查看端口对应的进程</li></ul><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p>端口有什么用呢?我们知道,一台拥有IP地址的主机可以提供许多服务,比如HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。</p><h3 id="socket简介"><a href="#socket简介" class="headerlink" title="socket简介"></a>socket简介</h3><h4 id="不同的电脑之间如何通信?"><a href="#不同的电脑之间如何通信?" class="headerlink" title="不同的电脑之间如何通信?"></a>不同的电脑之间如何通信?</h4><p>首要解决的问题是如何唯一标识一个进程,否则通信无从谈起! 在1台电脑上可以通过进程号(PID)来唯一标识一个进程,但是在网络中这是行不通的。 其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用进程(进程)。</p><p>这样利用 <strong><em>ip地址, 协议,端口</em></strong> 就可以标识网络的进程 。</p><p><strong>注意知识点:</strong></p><ul><li>所谓<code>进程</code>指的是:运行的程序以及运行时用到的资源这个整体称之为进程。</li><li>所谓<code>进程间通信</code>指的是:运行的程序之间的数据共享。</li></ul><h4 id="什么是socket?"><a href="#什么是socket?" class="headerlink" title="什么是socket?"></a>什么是socket?</h4><p>socket(简称<code>套接字</code>)是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于Socket 来完成通信的,例如我们每天浏览网页、QQ 聊天、收发email 等等。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字 (Socket)的接口,区分不同应用程序进程间的网络通信和连接。</p><h4 id="创建socket"><a href="#创建socket" class="headerlink" title="创建socket"></a>创建socket</h4><p>在Python 中使用socket 模块的函数socket 就可以完成:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> socket</span><br><span class="line">socket.socket(AddressFamily, Type)</span><br></pre></td></tr></table></figure><p><strong>说明:</strong></p><p>通过类socket.socket 创建一个socket对象,该对象带有两个参数:</p><ul><li>Address Family:可以选择AF_INET(用于Internet 进程间通信) 或者AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET。</li><li>Type:套接字类型,可以是SOCK_STREAM(流式套接字,主要用于TCP 协议)或者SOCK_DGRAM(数据报套接字,主要用于UDP 协议 。</li></ul><p>使用方式:</p><ol><li>创建套接字</li><li>使用套接字收/发数据</li><li>关闭套接字</li></ol><p>创建一个tcp socket(tcp套接字):</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建tcp的套接字</span></span><br><span class="line">s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line"></span><br><span class="line"><span class="comment"># ...这里是使用套接字的功能(省略)...</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 不用的时候,关闭套接字</span></span><br><span class="line">s.close()</span><br></pre></td></tr></table></figure><p>创建一个udp socket(udp套接字) :</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建udp的套接字</span></span><br><span class="line">s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</span><br><span class="line"></span><br><span class="line"><span class="comment"># ...这里是使用套接字的功能(省略)...</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 不用的时候,关闭套接字</span></span><br><span class="line">s.close()</span><br></pre></td></tr></table></figure><h2 id="udp网络程序-发送、接收数据"><a href="#udp网络程序-发送、接收数据" class="headerlink" title="udp网络程序-发送、接收数据"></a>udp网络程序-发送、接收数据</h2><h3 id="发送数据"><a href="#发送数据" class="headerlink" title="发送数据"></a>发送数据</h3><p>创建一个基于udp的网络程序流程很简单,具体步骤如下:</p><ol><li>创建客户端套接字</li><li>发送/接收数据</li><li>关闭套接字</li></ol><p><img src="https://s1.ax1x.com/2018/06/22/PSzWFS.png" alt=""></p><p>代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding=utf-8 _*_</span></span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 创建udp套接字</span></span><br><span class="line">udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 准备接收方的地址</span></span><br><span class="line"><span class="comment"># '192.168.30.71'表示目的ip地址</span></span><br><span class="line"><span class="comment"># 8080表示目的端口</span></span><br><span class="line">dest_addr = (<span class="string">'192.168.30.71'</span>, <span class="number">8080</span>) <span class="comment"># 注意是元组,ip是字符串,端口是数字</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 从键盘获取数据</span></span><br><span class="line">send_data = input(<span class="string">"请输入要发送的数据:"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 发送数据到指定的电脑上的指定程序中</span></span><br><span class="line">udp_socket.sendto(send_data.encode(<span class="string">'utf-8'</span>), dest_addr)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 关闭套接字</span></span><br><span class="line">udp_socket.close()</span><br></pre></td></tr></table></figure><p>运行的脚本:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># python 01_udp.py</span></span><br><span class="line">请输入要发送的数据: welcome to chenfanlinux.org!</span><br></pre></td></tr></table></figure><p>windows网络调试助手:</p><p><img src="https://s1.ax1x.com/2018/06/22/PpSNXn.png" alt=""></p><h3 id="发送、接收数据"><a href="#发送、接收数据" class="headerlink" title="发送、接收数据"></a>发送、接收数据</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding=utf-8 _*_</span></span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 创建udp套接字</span></span><br><span class="line">udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 准备接收方的地址</span></span><br><span class="line">dest_addr = (<span class="string">'192.168.30.71'</span>, <span class="number">8080</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 从键盘获取数据</span></span><br><span class="line">send_data = input(<span class="string">"请输入要发送的数据:"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 发送数据到指定的电脑上</span></span><br><span class="line">udp_socket.sendto(send_data.encode(<span class="string">'utf-8'</span>), dest_addr)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 等待接收对方发送的数据</span></span><br><span class="line">recv_data = udp_socket.recvfrom(<span class="number">1024</span>) <span class="comment"># 1024表示本次接收的最大字节数</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 显示对方发送的数据</span></span><br><span class="line"><span class="comment"># 接收到的数据recv_data是一个元组</span></span><br><span class="line"><span class="comment"># 第1个元素是对方发送的数据</span></span><br><span class="line"><span class="comment"># 第2个元素是对方的ip和端口</span></span><br><span class="line">print(recv_data[<span class="number">0</span>].decode(<span class="string">'gbk'</span>)) <span class="comment"># windows上用'gbk'编码,此处接收数据同样的方式解码。</span></span><br><span class="line">print(recv_data[<span class="number">1</span>])</span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 关闭套接字</span></span><br><span class="line">udp_socket.close()</span><br></pre></td></tr></table></figure><p>运行脚本:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># python 01_udp.py</span></span><br><span class="line">请输入要发送的数据: 你好啊,非常高兴看来我的博客!</span><br><span class="line">你的博客内容非常好啊,以后会经常来!</span><br><span class="line">(<span class="string">'127.0.0.1'</span>, 8080)</span><br></pre></td></tr></table></figure><p>windows网络调试助手:</p><p><img src="https://s1.ax1x.com/2018/06/22/PpSRn1.png" alt=""></p><h2 id="udp端口绑定"><a href="#udp端口绑定" class="headerlink" title="udp端口绑定"></a>udp端口绑定</h2><h3 id="会变的端口号"><a href="#会变的端口号" class="headerlink" title="会变的端口号"></a>会变的端口号</h3><p>重新运行多次脚本,然后在“网络调试助手”中,看到的现象如下:</p><p><img src="https://s1.ax1x.com/2018/06/22/PpS5tO.png" alt=""></p><p>说明:</p><ul><li>每重新运行一次网络程序,上图中红圈中的数字,不一样的原因在于,这个数字标识这个网络程序,当重新运行时,如果没有确定到底用哪个,系统默认会随机分配。</li><li>记住一点:这个网络程序在运行的过程中,这个就唯一标识这个程序,所以如果其他电脑上的网络程序如果想要向此程序发送数据,那么就需要向这个数字(即端口)标识的程序发送即可。</li></ul><h3 id="udp绑定信息"><a href="#udp绑定信息" class="headerlink" title="udp绑定信息"></a>udp绑定信息</h3><p>一般情况下,在一台电脑上运行的网络程序有很多,为了不与其他的网络程序占用同一个端口号,往往在编程中,udp的端口号一般不绑定 。但是如果需要做成一个服务器端的程序的话,是需要绑定的 。</p><p>代码实例:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding=utf-8 _*_</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 创建套接字</span></span><br><span class="line">udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配</span></span><br><span class="line">local_addr = (<span class="string">''</span>, <span class="number">7788</span>) <span class="comment"># ip地址和端口号,ip一般不用写,表示本机的任何一个ip</span></span><br><span class="line">udp_socket.bind(local_addr)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 等待接收对方发送的数据</span></span><br><span class="line">recv_data = udp_socket.recvfrom(<span class="number">1024</span>) <span class="comment"># 1024表示本次接收的最大字节数</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 显示接收到的数据</span></span><br><span class="line">print(recv_data[<span class="number">0</span>].decode(<span class="string">'gbk'</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 关闭套接字</span></span><br><span class="line">udp_socket.close()</span><br></pre></td></tr></table></figure><p>windows网络调试助手:</p><p><img src="https://s1.ax1x.com/2018/06/22/Pp99IK.png" alt=""></p><p>代码接收到的结果:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">λ python 01_udp.py</span><br><span class="line">你好,我知道你绑定了端口7788,以后通过这个端口和你通信。</span><br></pre></td></tr></table></figure><h3 id="总结-1"><a href="#总结-1" class="headerlink" title="总结"></a>总结</h3><ul><li>一个udp网络程序,可以不绑定,此时操作系统会随机进行分配一个端口,如果重新运行此程序端口可能会发生变化。</li><li>一个udp网络程序,也可以绑定信息(ip地址,端口号),如果绑定成功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的。</li></ul><h2 id="应用:udp聊天器"><a href="#应用:udp聊天器" class="headerlink" title="应用:udp聊天器"></a>应用:udp聊天器</h2><h3 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h3><p>在一个电脑中编写1个程序,有2个功能。</p><ul><li>1.获取键盘数据,并将其发送给对方</li><li>2.接收数据并显示</li><li>3.并且功能数据进行选择以上的2个功能调用</li></ul><h3 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding:utf8 _*_</span></span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string">在一个电脑中编写1个程序,有2个功能</span></span><br><span class="line"><span class="string">1.获取键盘数据,并将其发送给对方</span></span><br><span class="line"><span class="string">2.接收数据并显示</span></span><br><span class="line"><span class="string">并且功能数据进行选择以上的2个功能调用</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">send_data</span><span class="params">(udp_socket)</span>:</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 获取对方的ip/port</span></span><br><span class="line"> dest_ip = input(<span class="string">"请输入对方的ip: "</span>)</span><br><span class="line"> dest_port = int(input(<span class="string">"请输入对方的port: "</span>))</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 从键盘获取数据</span></span><br><span class="line"> send_data = input(<span class="string">"请输入要发送的数据: "</span>)</span><br><span class="line"> <span class="comment"># 可以使用套接字收发数据,发送任意数据,这里编码为bytes</span></span><br><span class="line"> udp_socket.sendto(send_data.encode(<span class="string">"utf-8"</span>), (dest_ip, dest_port))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">recv_data</span><span class="params">(udp_socket)</span>:</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 接收回送过来的数据</span></span><br><span class="line"> recv_data = udp_socket.recvfrom(<span class="number">1024</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 解码</span></span><br><span class="line"> recv_ip = str(recv_data[<span class="number">1</span>])</span><br><span class="line"> recv_msg = recv_data[<span class="number">0</span>].decode(<span class="string">'gbk'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 打印收到的数据</span></span><br><span class="line"> recv_msg = <span class="string">"%s: %s"</span> % (recv_ip, recv_msg)</span><br><span class="line"> print(recv_msg)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="comment"># 创建套接字</span></span><br><span class="line"> udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)</span><br><span class="line"> <span class="comment"># 绑定本地信息</span></span><br><span class="line"> udp_socket.bind((<span class="string">""</span>, <span class="number">7890</span>))</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line"> <span class="comment"># 选择功能</span></span><br><span class="line"> print(<span class="string">"="</span> * <span class="number">30</span>)</span><br><span class="line"> print(<span class="string">"1:发送消息"</span>)</span><br><span class="line"> print(<span class="string">"2:接收消息"</span>)</span><br><span class="line"> print(<span class="string">"="</span> * <span class="number">30</span>)</span><br><span class="line"> op = input(<span class="string">"请选择您要选择的功能: "</span>)</span><br><span class="line"> <span class="keyword">if</span> op == <span class="string">"1"</span>:</span><br><span class="line"> <span class="comment"># 发送数据</span></span><br><span class="line"> send_data(udp_socket)</span><br><span class="line"> <span class="keyword">elif</span> op == <span class="string">"2"</span>:</span><br><span class="line"> <span class="comment"># 接收数据</span></span><br><span class="line"> recv_data(udp_socket)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">"输入有误,请重新输入..."</span>)</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 关闭套接字</span></span><br><span class="line"> udp_socket.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure><h3 id="功能演练"><a href="#功能演练" class="headerlink" title="功能演练"></a>功能演练</h3><p>脚本运行:</p><p><img src="https://s1.ax1x.com/2018/06/22/PpCZpF.png" alt=""></p><p>windows调试工具:</p><p><img src="https://s1.ax1x.com/2018/06/22/PpCKmR.png" alt=""></p>]]></content>
<summary type="html">
<h2 id="网络编程中的重要概念"><a href="#网络编程中的重要概念" class="headerlink" title="网络编程中的重要概念"></a>网络编程中的重要概念</h2><blockquote>
<p>所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信。</p>
</blockquote>
<h3 id="网络"><a href="#网络" class="headerlink" title="网络"></a>网络</h3><ul>
<li>使用网络能够把多方链接在一起,然后可以进行数据传递</li>
<li>所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信</li>
</ul>
<h3 id="ip地址"><a href="#ip地址" class="headerlink" title="ip地址"></a>ip地址</h3><p><strong>用来在网络中标记一台电脑,比如192.168.1.1;在本地局域网上是唯一的。每一个IP地址包括两部分:网络地址和主机地址。</strong></p>
<ul>
<li><p>一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”,</p>
<p>地址范围1.0.0.1-126.255.255.254。</p>
</li>
<li><p>一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,</p>
<p>地址范围128.1.0.1-191.255.255.254。</p>
</li>
<li><p>一个C类IP地址由3字节的网络地址和1字节的主机地址组成,网络地址的最高位必须是“110”</p>
<p>范围192.0.1.1-223.255.255.254。</p>
</li>
<li><p>D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。</p>
</li>
<li><p>E类地址保留,仅作实验和开发用 。</p>
</li>
<li><p>在这么多网络IP中,国际规定有一部分IP地址是用于我们的局域网使用,也就</p>
<p>是属于私网IP。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 私网ip的地址</span></span><br><span class="line">10.0.0.0~10.255.255.255</span><br><span class="line">172.16.0.0~172.31.255.255</span><br><span class="line">192.168.0.0~192.168.255.255</span><br></pre></td></tr></table></figure>
</li>
</ul>
</summary>
<category term="Python网络编程" scheme="http://www.chenfanlinux.org/categories/Python%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/"/>
<category term="upd网络编程" scheme="http://www.chenfanlinux.org/tags/upd%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>运维自动化工具Ansible</title>
<link href="http://www.chenfanlinux.org/2018/06/07/%E8%BF%90%E7%BB%B4%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7Ansible/"/>
<id>http://www.chenfanlinux.org/2018/06/07/运维自动化工具Ansible/</id>
<published>2018-06-07T08:46:07.000Z</published>
<updated>2018-06-07T08:48:01.000Z</updated>
<content type="html"><![CDATA[<h2 id="Ansible简介"><a href="#Ansible简介" class="headerlink" title="Ansible简介"></a>Ansible简介</h2><h3 id="Ansible-是什么?"><a href="#Ansible-是什么?" class="headerlink" title="Ansible 是什么?"></a>Ansible 是什么?</h3><p><strong>Ansible</strong> 简单的说是一个配置管理系统(configuration management system)。你只需要可以使用 ssh 访问你的服务器或设备就行。它也不同于其他工具,因为它使用推送的方式,而不是像 puppet 等 那样使用拉取安装agent的方式。你可以将代码部署到任意数量的服务器上!</p><h3 id="Ansible能做什么?"><a href="#Ansible能做什么?" class="headerlink" title="Ansible能做什么?"></a>Ansible能做什么?</h3><blockquote><p>ansible可以帮助我们完成一些批量任务,或者完成一些需要经常重复的工作,这些场景中我们都可以使用到ansible。</p></blockquote><ul><li>同时在100台服务器上安装nginx服务,并在安装后启动它们</li><li>将某个文件一次性拷贝到100台服务器上。</li><li>每当有新服务器加入工作环境时,你都要为新服务器部署某个服务,也就是说你需要经常重复的完成相同的工作。</li></ul><h3 id="Ansible特性"><a href="#Ansible特性" class="headerlink" title="Ansible特性"></a>Ansible特性</h3><ul><li>模块化:调用特定的模块,完成特定的任务。</li><li>有Paramiko, PyYAMl, Jinja2(模板语言) 三个关键模块</li><li>支持自定义模块</li><li>基于Python语言实现</li><li>部署简单,基于python和SSH(默认已安装), agentless</li><li>安全,基于OpenSSH</li><li>支持playbook任务编排</li><li>幂等性:一次任务执行一遍和执行n遍效果一样,不会重复执行带来意外情况</li><li>无需代理不依赖PKI(无需ssl)</li><li>可使用任何编程语言写模块</li><li>YAML格式,编排任务,丰富的数据结构</li><li>较强大的多层解决方案</li></ul><h3 id="Ansible架构"><a href="#Ansible架构" class="headerlink" title="Ansible架构"></a>Ansible架构</h3><p><img src="https://s1.ax1x.com/2018/06/07/CHJYMF.png" alt="ansible"></p><h3 id="Ansible主要组成部分功能说明"><a href="#Ansible主要组成部分功能说明" class="headerlink" title="Ansible主要组成部分功能说明"></a>Ansible主要组成部分功能说明</h3><ul><li><strong>PLAYBOOKS</strong>:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YAML文件。</li><li><strong>INVENTORY</strong>: Ansible管理主机的清单/etc/anaible/hosts。</li><li><strong>MODULES</strong>: Ansible执行命令的功能模块,多数为内置的核心模块,也可自定义,ansible-doc –l 可查看模块。</li><li><strong>PLUGINS</strong>: 模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用。</li><li><strong>API</strong>:供第三方程序调用的应用程序编程接口。</li><li><strong>ANSIBLE</strong>:组合INVENTORY、 API、 MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具。</li></ul><a id="more"></a><p><strong>注意事项</strong> :</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">- 执行ansible的主机一般称为主控端,中控,master或堡垒机</span><br><span class="line">- 主控端Python版本需要2.6或以上</span><br><span class="line">- 被控端Python版本小于2.4需要安装python-simplejson</span><br><span class="line">- 被控端如开启SELinux需要安装libselinux-python</span><br><span class="line">- windows不能做为主控端</span><br></pre></td></tr></table></figure><h2 id="安装与配置Ansible"><a href="#安装与配置Ansible" class="headerlink" title="安装与配置Ansible"></a>安装与配置Ansible</h2><h3 id="安装Ansible"><a href="#安装Ansible" class="headerlink" title="安装Ansible"></a>安装Ansible</h3><p>安装方法有很多 , 这里仅仅以Centos yum安装为例 , Ansible默认不在标准仓库中,需要用到EPEL源。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># yum install -y epel-release</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># yum -y install ansible</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible --version</span></span><br><span class="line">ansible 2.5.3</span><br><span class="line"> config file = /etc/ansible/ansible.cfg</span><br><span class="line"> configured module search path = [u<span class="string">'/root/.ansible/plugins/modules'</span>, u<span class="string">'/usr/share/ansible/plugins/modules'</span>]</span><br><span class="line"> ansible python module location = /usr/lib/python2.7/site-packages/ansible</span><br><span class="line"> executable location = /usr/bin/ansible</span><br><span class="line"> python version = 2.7.5 (default, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]</span><br></pre></td></tr></table></figure><h3 id="免秘钥登录"><a href="#免秘钥登录" class="headerlink" title="免秘钥登录"></a>免秘钥登录</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ssh-keygen</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ssh-copy-id test-node01</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ssh-copy-id test-node02</span></span><br></pre></td></tr></table></figure><h3 id="Ansible-配置文件"><a href="#Ansible-配置文件" class="headerlink" title="Ansible 配置文件"></a>Ansible 配置文件</h3><p>Ansible 配置文件/etc/ansible/ansible.cfg (一般保持默认)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"> [defaults]</span><br><span class="line"> #inventory = /etc/ansible/hosts # 主机列表配置文件</span><br><span class="line"> #library = /usr/share/my_modules/ # 库文件存放目录</span><br><span class="line"> #remote_tmp = $HOME/.ansible/tmp #临时py命令文件存放在远程主机目录</span><br><span class="line"> #local_tmp = $HOME/.ansible/tmp # 本机的临时命令执行目录</span><br><span class="line"> #forks = 5 # 默认并发数</span><br><span class="line"> #sudo_user = root # 默认sudo 用户</span><br><span class="line"> #ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码</span><br><span class="line"> #ask_pass = True #连接时提示输入ssh密码</span><br><span class="line"> #remote_port = 22 #远程主机的默认端口,生产中这个端口应该会不同</span><br><span class="line"> #log_path = /var/log/ansible.log #日志</span><br><span class="line"> #host_key_checking = False # 检查对应服务器的host_key,建议取消注释。也就是不会弹出</span><br></pre></td></tr></table></figure><p><img src="https://s1.ax1x.com/2018/06/07/CHYleH.png" alt="ansible配置文件"></p><h3 id="Inventory-主机清单"><a href="#Inventory-主机清单" class="headerlink" title="Inventory 主机清单"></a>Inventory 主机清单</h3><p>Ansible必须通过Inventory 来管理主机。Ansible 可同时操作属于一个组的多台主机,组和主机之间的关系通过 inventory 文件配置。</p><p><strong>语法格式:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1.单台主机</span></span><br><span class="line"><span class="built_in">test</span>-master01 或者 192.168.72.2</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 定义组</span></span><br><span class="line">[node]</span><br><span class="line"><span class="built_in">test</span>-node01</span><br><span class="line"><span class="built_in">test</span>-node02</span><br><span class="line"></span><br><span class="line">[db]</span><br><span class="line"><span class="built_in">test</span>-node02 <span class="comment"># 一台主机可以是不同的组</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 组内嵌套</span></span><br><span class="line">[group1:children] <span class="comment"># 组嵌套组,group1为自定义的组名,children是关键字,固定语法,必须填写。</span></span><br><span class="line">node <span class="comment"># group组内包含的其他组名</span></span><br><span class="line">db <span class="comment"># group组内包含的其他组名</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 分组主机可以简写</span></span><br><span class="line">[databases]</span><br><span class="line">db-[a:e].example.com</span><br><span class="line">这里表示相当于:</span><br><span class="line">db-a.example.com</span><br><span class="line">db-b.example.com</span><br><span class="line">db-c.example.com</span><br><span class="line">db-d.example.com</span><br><span class="line">db-e.example.com</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 隐藏所有主机分组all</span></span><br><span class="line">最后还有一个隐藏的分组,那就是all,代表全部主机,这个是隐式的,不需要写出来的。</span><br></pre></td></tr></table></figure><h2 id="Ansible使用"><a href="#Ansible使用" class="headerlink" title="Ansible使用"></a>Ansible使用</h2><h3 id="Ansible常用命令语法"><a href="#Ansible常用命令语法" class="headerlink" title="Ansible常用命令语法"></a>Ansible常用命令语法</h3><p><strong>通用语法:</strong> <code>ansible <host-pattern> [-m module_name] [options]</code></p><p> <code>指令 匹配规则的主机清单 -m 模块名 选项</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">--version 显示版本</span><br><span class="line">-a 模块参数(如果有)</span><br><span class="line">-m module 指定模块,默认为<span class="built_in">command</span></span><br><span class="line">-v 详细过程 –vv -vvv更详细</span><br><span class="line">--list-hosts 显示主机列表,可简写--list</span><br><span class="line">-k, --ask-pass 提示连接密码,默认Key验证</span><br><span class="line">-K,--ask-become-pass 提示使用sudo密码</span><br><span class="line">-C, --check 检查,并不执行</span><br><span class="line">-T, --timeout=TIMEOUT 执行命令的超时时间,默认10s</span><br><span class="line">-u, --user=REMOTE_USER 执行远程执行的用户</span><br><span class="line">-U, SUDO_USER, --sudo-user 指定sudu用户</span><br><span class="line">-b, --become 代替旧版的sudo 切换</span><br></pre></td></tr></table></figure><p><strong>查看模块帮助:</strong> <code>ansible-doc [options][module...]</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ansible-doc: 显示模块帮助</span><br><span class="line">ansible-doc [options] [module...]</span><br><span class="line"></span><br><span class="line">-a 显示所有模块的文档</span><br><span class="line">-l, --list 列出可用模块</span><br><span class="line">-s, --snippet 显示指定模块的简要说明</span><br></pre></td></tr></table></figure><h3 id="Ansible-主机-匹配列表"><a href="#Ansible-主机-匹配列表" class="headerlink" title="Ansible 主机 匹配列表"></a>Ansible 主机 匹配列表</h3><p><strong>使用通配符</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">* 匹配任意字符</span><br><span class="line"><span class="comment"># ansible '*' --list 等同于 # ansible all --list</span></span><br><span class="line"></span><br><span class="line">? 匹配单个字符</span><br><span class="line"><span class="comment"># ansible 'test-node0?' --list</span></span><br><span class="line"></span><br><span class="line">: 或者 --> 在组node或master</span><br><span class="line"><span class="comment"># ansible 'node:master' --list</span></span><br><span class="line"></span><br><span class="line">:& 并且 (逻辑与) ---> 在组node和master中</span><br><span class="line"><span class="comment"># ansible 'node:&master' --list</span></span><br><span class="line"></span><br><span class="line">:! 逻辑非 ---> 在组master内,却不在node内</span><br><span class="line"><span class="comment"># ansible 'master:!node' --list</span></span><br></pre></td></tr></table></figure><p><strong>使用正则表达式</strong></p><p>~表示后面是正则匹配,注意~后面不能有空格</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># ansible '~^[[:digit:]]' --list</span></span><br></pre></td></tr></table></figure><h3 id="Ansible-的命令执行过程"><a href="#Ansible-的命令执行过程" class="headerlink" title="Ansible 的命令执行过程"></a>Ansible 的命令执行过程</h3><p>以 <code>ansible test-node01 -m command -a 'ls -l /' -vvv</code> 这条命令为例,根据显示的信息时行解读</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">1>. 加载自己的配置文件,默认/etc/ansible/ansible.cfg</span><br><span class="line">Using /etc/ansible/ansible.cfg as config file</span><br><span class="line"></span><br><span class="line">2>. 匹配主机清单</span><br><span class="line">Parsed /etc/ansible/hosts inventory <span class="built_in">source</span> with ini plugin</span><br><span class="line"></span><br><span class="line">3>. 加载指令对应的模块文件</span><br><span class="line">Using module file /usr/lib/python2.7/site-packages/ansible/modules/commands/command.py</span><br><span class="line"></span><br><span class="line">4>. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户<span class="variable">$HOME</span>/.ansible/tmp/ansible-tmp-数字/XXX.PY文件,这个目录就是在/etc/ansible/ansible.cfg定义的</span><br><span class="line"> ( <span class="built_in">umask</span> 77 && mkdir -p <span class="string">"` echo /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861 `"</span> ....)</span><br><span class="line"> sftp> put /tmp/tmp4JvsLH /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/command.py\n<span class="string">'</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">5>. 给文件 +x 权限</span></span><br><span class="line"><span class="string"> '</span>chmod u+x /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/ /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/command.py && sleep 0<span class="string">'</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">6>. 执行并返回结果</span></span><br><span class="line"><span class="string"> '</span>/usr/bin/python /root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/command.py;</span><br><span class="line"></span><br><span class="line">7>. 删除临时py文件,sleep 0退出</span><br><span class="line">rm -rf <span class="string">"/root/.ansible/tmp/ansible-tmp-1517301292.6-155771303493861/"</span> > /dev/null 2>&1 && sleep 0</span><br><span class="line"></span><br><span class="line">8>. 断开远程主机连接</span><br><span class="line"><span class="string">'Shared connection to 7-db-3.hunk.tech closed.\r\n'</span>)</span><br></pre></td></tr></table></figure><h3 id="执行结果状态"><a href="#执行结果状态" class="headerlink" title="执行结果状态"></a>执行结果状态</h3><ul><li>绿色:执行成功并且不需要做改变的操作</li><li>×××:执行成功并且对目标主机做变更</li><li>红色:执行失败</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">可以在配置文件中定义</span><br><span class="line">[colors]</span><br><span class="line"><span class="comment">#highlight = white</span></span><br><span class="line"><span class="comment">#verbose = blue</span></span><br><span class="line"><span class="comment">#warn = bright purple</span></span><br><span class="line"><span class="comment">#error = red</span></span><br><span class="line"><span class="comment">#debug = dark gray</span></span><br><span class="line"><span class="comment">#deprecate = purple</span></span><br><span class="line"><span class="comment">#skip = cyan</span></span><br><span class="line"><span class="comment">#unreachable = red</span></span><br><span class="line"><span class="comment">#ok = green</span></span><br><span class="line"><span class="comment">#changed = yellow</span></span><br><span class="line"><span class="comment">#diff_add = green</span></span><br><span class="line"><span class="comment">#diff_remove = red</span></span><br><span class="line"><span class="comment">#diff_lines = cyan</span></span><br></pre></td></tr></table></figure><h2 id="Ansible常用模块的使用"><a href="#Ansible常用模块的使用" class="headerlink" title="Ansible常用模块的使用"></a>Ansible常用模块的使用</h2><blockquote><p>Ansible的模板非常的重要,这里要非常详细的学习</p></blockquote><h3 id="ping"><a href="#ping" class="headerlink" title="ping"></a>ping</h3><p>功能:尝试连接到主机,验证并返回pong成功。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看模块的简要说明</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible-doc -s ping</span></span><br><span class="line">- name: Try to connect to host, verify a usable python and <span class="built_in">return</span> `pong<span class="string">' on success</span></span><br><span class="line"><span class="string"> ping:</span></span><br><span class="line"><span class="string"> data: # Data to return for the `ping'</span> <span class="built_in">return</span> value. If this parameter is <span class="built_in">set</span> to `crash<span class="string">', the module will cause an exception.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[root@test-master01 ~]# ansible all -m ping</span></span><br><span class="line"><span class="string">test-node02 | SUCCESS => {</span></span><br><span class="line"><span class="string"> "changed": false,</span></span><br><span class="line"><span class="string"> "ping": "pong" # 返回pong表明成功通讯</span></span><br><span class="line"><span class="string">}</span></span><br><span class="line"><span class="string">test-master01 | SUCCESS => {</span></span><br><span class="line"><span class="string"> "changed": false,</span></span><br><span class="line"><span class="string"> "ping": "pong"</span></span><br><span class="line"><span class="string">}</span></span><br><span class="line"><span class="string">test-node01 | SUCCESS => {</span></span><br><span class="line"><span class="string"> "changed": false,</span></span><br><span class="line"><span class="string"> "ping": "pong"</span></span><br><span class="line"><span class="string">}</span></span><br></pre></td></tr></table></figure><h3 id="command"><a href="#command" class="headerlink" title="command"></a>command</h3><p>功能:在远程节点上执行命令 。</p><ul><li>变量 和操作符号 “<”, “>”, “|”, “;” and “&” 不能正常工作。如果需要使用,请使用shell模块。</li><li>Ansible默认不指定模块时,将使用此模块。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">- <span class="built_in">chdir</span> 命令运行前先切换到此目录。 ansible <span class="built_in">test</span>-node01 -a <span class="string">'chdir=/tmp ls'</span></span><br><span class="line">- creates 条件判断,如果文件存在,将不执行后面的命令。 ansible <span class="built_in">test</span>-node01 -a <span class="string">'creates=/tmp rm -f test.py'</span></span><br><span class="line">- removes 条件判断,如果文件不存在,将不执行后面的命令。ansible <span class="built_in">test</span>-node01 -a <span class="string">'removes=/tmp rm -f test.py'</span></span><br><span class="line">- stdin 将命令的stdin直接设置为指定的值</span><br><span class="line">- warn 如果 ansible.cfg 设置了开启警报, 将不会对这一行进行警报</span><br></pre></td></tr></table></figure><h3 id="shell"><a href="#shell" class="headerlink" title="shell"></a>shell</h3><p>功能:在远程节点上执行命令。与command模快使用一致,但是,变量 和操作符号 “<”, “>”, “|”, “;” and “&” 能正常工作。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 下面2个例子对比能清晰的表示出不同的地方</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m command -a 'echo $RANDOM'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS | rc=0 >></span><br><span class="line"><span class="variable">$RANDOM</span></span><br><span class="line"></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m shell -a 'echo $RANDOM'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS | rc=0 >></span><br><span class="line">19077</span><br><span class="line"></span><br><span class="line"><span class="comment"># 这些复杂命令,即使使用shell也可能会失败,解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器。</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m shell -a df | awk '{print $5}'</span></span><br></pre></td></tr></table></figure><h3 id="script"><a href="#script" class="headerlink" title="script"></a>script</h3><p>功能:把脚本复制到远程节点后,在远程节点本地运行脚本 ,给定的脚本将通过远程节点上的shell环境进行处理。这个模块在远程系统上不需要python,就像原始脚本一样。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node02 -m script -a 'hello.sh'</span></span><br><span class="line"><span class="built_in">test</span>-node02 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"rc"</span>: 0,</span><br><span class="line"> <span class="string">"stderr"</span>: <span class="string">"Shared connection to test-node02 closed.\r\n"</span>,</span><br><span class="line"> <span class="string">"stdout"</span>: <span class="string">"hello welcome to chenfanlinux.org\r\n"</span>,</span><br><span class="line"> <span class="string">"stdout_lines"</span>: [</span><br><span class="line"> <span class="string">"hello welcome to chenfanlinux.org"</span></span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="copy"><a href="#copy" class="headerlink" title="copy"></a>copy</h3><p>功能:复制文件或目录到远程节点。默认会覆盖目标文件 。</p><p><strong>参数详解:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">- src:要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用<span class="string">"/"</span>来结尾,则只复制目录里的内容,如果没有使用<span class="string">"/"</span>来结尾,则包含目录在内的整个内容全部复制,类似于rsync。</span><br><span class="line">- dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录。</span><br><span class="line">- backup:在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no</span><br><span class="line">- content:用于替代<span class="string">"src"</span>,可以直接设定指定文件的内容,相当于<span class="built_in">echo</span> 重定向内容到文件</span><br><span class="line">- directory_mode:递归的设定目录的权限,默认为系统默认权限</span><br><span class="line">- force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes</span><br><span class="line">- others:所有的file模块里的选项都可以在这里使用</span><br></pre></td></tr></table></figure><p><strong>实例说明:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 复制文件</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m copy -a 'src=hello.sh dest=/root backup=yes'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"checksum"</span>: <span class="string">"449c7df7cfc5a34a19f3e6dc64bb739fa066c650"</span>,</span><br><span class="line"> <span class="string">"dest"</span>: <span class="string">"/root/hello.sh"</span>,</span><br><span class="line"> <span class="string">"gid"</span>: 0,</span><br><span class="line"> <span class="string">"group"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"md5sum"</span>: <span class="string">"a1c5800f3a303d01101a2861dd37b165"</span>,</span><br><span class="line"> <span class="string">"mode"</span>: <span class="string">"0644"</span>,</span><br><span class="line"> <span class="string">"owner"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"size"</span>: 53,</span><br><span class="line"> <span class="string">"src"</span>: <span class="string">"~None/.ansible/tmp/ansible-tmp-1528359468.11-74900633617667/source"</span>,</span><br><span class="line"> <span class="string">"state"</span>: <span class="string">"file"</span>,</span><br><span class="line"> <span class="string">"uid"</span>: 0</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment"># 复制目录时,斜线不要写,这样可以将thid_dir 目录复制到远程的root下</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># mkdir this_dir # 文件底下需要有内容</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># touch this_dir/test.text</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m copy -a 'src=/root/this_dir dest=/root backup=yes'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"checksum"</span>: <span class="string">"da39a3ee5e6b4b0d3255bfef95601890afd80709"</span>,</span><br><span class="line"> <span class="string">"dest"</span>: <span class="string">"/root/this_dir/test.text"</span>,</span><br><span class="line"> <span class="string">"gid"</span>: 0,</span><br><span class="line"> <span class="string">"group"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"md5sum"</span>: <span class="string">"d41d8cd98f00b204e9800998ecf8427e"</span>,</span><br><span class="line"> <span class="string">"mode"</span>: <span class="string">"0644"</span>,</span><br><span class="line"> <span class="string">"owner"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"size"</span>: 0,</span><br><span class="line"> <span class="string">"src"</span>: <span class="string">"~None/.ansible/tmp/ansible-tmp-1528359562.1-256280234210712/source"</span>,</span><br><span class="line"> <span class="string">"state"</span>: <span class="string">"file"</span>,</span><br><span class="line"> <span class="string">"uid"</span>: 0</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="file"><a href="#file" class="headerlink" title="file"></a>file</h3><p>功能:文件操作及属性设置</p><p><strong>参数详解:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">force:需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no</span><br><span class="line">group:定义文件/目录的属组</span><br><span class="line">mode:定义文件/目录的权限</span><br><span class="line">owner:定义文件/目录的属主</span><br><span class="line">path:必选项,定义文件/目录的路径</span><br><span class="line">recurse:递归的设置文件的属性,只对目录有效</span><br><span class="line">src:要被链接的源文件的路径,只应用于state=link的情况</span><br><span class="line">dest:被链接到的路径,只应用于state=link的情况</span><br><span class="line">state: 操作方法</span><br><span class="line"> directory:如果目录不存在,创建目录</span><br><span class="line"> file:即使文件不存在,也不会被创建</span><br><span class="line"> link:创建软链接</span><br><span class="line"> hard:创建硬链接</span><br><span class="line"> touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间</span><br><span class="line"> absent:删除目录、文件或者取消链接文件。相当于rm -rf</span><br></pre></td></tr></table></figure><p><strong>实例说明:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建空文件,类似于touch</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m file -a 'path=/root/null.txt state=touch mode=0666 owner=root'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"dest"</span>: <span class="string">"/root/null.txt"</span>,</span><br><span class="line"> <span class="string">"gid"</span>: 0,</span><br><span class="line"> <span class="string">"group"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"mode"</span>: <span class="string">"0666"</span>,</span><br><span class="line"> <span class="string">"owner"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"size"</span>: 0,</span><br><span class="line"> <span class="string">"state"</span>: <span class="string">"file"</span>,</span><br><span class="line"> <span class="string">"uid"</span>: 0</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建空目录, 类似于mkdir -p</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m file -a 'path=/root/dir1/dir2/dir3 state=directory mode=0666 owner=root'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"gid"</span>: 0,</span><br><span class="line"> <span class="string">"group"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"mode"</span>: <span class="string">"0666"</span>,</span><br><span class="line"> <span class="string">"owner"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"path"</span>: <span class="string">"/root/dir1/dir2/dir3"</span>,</span><br><span class="line"> <span class="string">"size"</span>: 4096,</span><br><span class="line"> <span class="string">"state"</span>: <span class="string">"directory"</span>,</span><br><span class="line"> <span class="string">"uid"</span>: 0</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建软链接</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m file -a 'path=/root/hello state=link src=/root/hello.py mode=0666 owner=root'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"dest"</span>: <span class="string">"/root/hello"</span>,</span><br><span class="line"> <span class="string">"gid"</span>: 0,</span><br><span class="line"> <span class="string">"group"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"mode"</span>: <span class="string">"0777"</span>,</span><br><span class="line"> <span class="string">"owner"</span>: <span class="string">"root"</span>,</span><br><span class="line"> <span class="string">"size"</span>: 14,</span><br><span class="line"> <span class="string">"src"</span>: <span class="string">"/root/hello.py"</span>,</span><br><span class="line"> <span class="string">"state"</span>: <span class="string">"link"</span>,</span><br><span class="line"> <span class="string">"uid"</span>: 0</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">[root@<span class="built_in">test</span>-node01 ~]<span class="comment"># ls hello -l</span></span><br><span class="line">lrwxrwxrwx 1 root root 14 Jun 7 16:30 hello -> /root/hello.py</span><br></pre></td></tr></table></figure><h3 id="cron"><a href="#cron" class="headerlink" title="cron"></a>cron</h3><p>功能:管理计划任务</p><p><strong>参数详解:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">backup:对远程主机上的原任务计划内容修改之前做备份</span><br><span class="line">cron_file:如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划</span><br><span class="line">day:日(1-31,*,*/2,……)</span><br><span class="line">hour:小时(0-23,*,*/2,……)</span><br><span class="line">minute:分钟(0-59,*,*/2,……)</span><br><span class="line">month:月(1-12,*,*/2,……)</span><br><span class="line">weekday:周(0-7,*,……)</span><br><span class="line">job:要执行的任务,依赖于state=present</span><br><span class="line">name:该任务的描述</span><br><span class="line">special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly</span><br><span class="line">state:确认该任务计划是创建还是删除</span><br><span class="line">user:以哪个用户的身份执行</span><br></pre></td></tr></table></figure><p><strong>实例说明:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 设置一个定时任务</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m cron -a 'name="test cron job" minute=*/2 job="/usr/bin/wall hello world"'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"envs"</span>: [],</span><br><span class="line"> <span class="string">"jobs"</span>: [</span><br><span class="line"> <span class="string">"test cron job"</span></span><br><span class="line"> ]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">[root@<span class="built_in">test</span>-node01 ~]<span class="comment"># crontab -l</span></span><br><span class="line"><span class="comment">#Ansible: test cron job</span></span><br><span class="line">*/2 * * * * /usr/bin/wall hello world</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 禁用某个计划任务</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m cron -a 'disabled=yes name="test cron job" minute=*/2 job="/usr/bin/wall hello world"'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"envs"</span>: [],</span><br><span class="line"> <span class="string">"jobs"</span>: [</span><br><span class="line"> <span class="string">"test cron job"</span></span><br><span class="line"> ]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">[root@<span class="built_in">test</span>-node01 ~]<span class="comment"># crontab -l</span></span><br><span class="line"><span class="comment">#Ansible: test cron job</span></span><br><span class="line"><span class="comment">#*/2 * * * * /usr/bin/wall hello world</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除某个定时任务</span></span><br><span class="line">[root@<span class="built_in">test</span>-master01 ~]<span class="comment"># ansible test-node01 -m cron -a 'state=absent name="test cron job"'</span></span><br><span class="line"><span class="built_in">test</span>-node01 | SUCCESS => {</span><br><span class="line"> <span class="string">"changed"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"envs"</span>: [],</span><br><span class="line"> <span class="string">"jobs"</span>: []</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">[root@<span class="built_in">test</span>-node01 ~]<span class="comment"># crontab -l</span></span><br><span class="line"><span class="comment"># 这时定时任务空了</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="Ansible简介"><a href="#Ansible简介" class="headerlink" title="Ansible简介"></a>Ansible简介</h2><h3 id="Ansible-是什么?"><a href="#Ansible-是什么?" class="headerlink" title="Ansible 是什么?"></a>Ansible 是什么?</h3><p><strong>Ansible</strong> 简单的说是一个配置管理系统(configuration management system)。你只需要可以使用 ssh 访问你的服务器或设备就行。它也不同于其他工具,因为它使用推送的方式,而不是像 puppet 等 那样使用拉取安装agent的方式。你可以将代码部署到任意数量的服务器上!</p>
<h3 id="Ansible能做什么?"><a href="#Ansible能做什么?" class="headerlink" title="Ansible能做什么?"></a>Ansible能做什么?</h3><blockquote>
<p>ansible可以帮助我们完成一些批量任务,或者完成一些需要经常重复的工作,这些场景中我们都可以使用到ansible。</p>
</blockquote>
<ul>
<li>同时在100台服务器上安装nginx服务,并在安装后启动它们</li>
<li>将某个文件一次性拷贝到100台服务器上。</li>
<li>每当有新服务器加入工作环境时,你都要为新服务器部署某个服务,也就是说你需要经常重复的完成相同的工作。</li>
</ul>
<h3 id="Ansible特性"><a href="#Ansible特性" class="headerlink" title="Ansible特性"></a>Ansible特性</h3><ul>
<li>模块化:调用特定的模块,完成特定的任务。</li>
<li>有Paramiko, PyYAMl, Jinja2(模板语言) 三个关键模块</li>
<li>支持自定义模块</li>
<li>基于Python语言实现</li>
<li>部署简单,基于python和SSH(默认已安装), agentless</li>
<li>安全,基于OpenSSH</li>
<li>支持playbook任务编排</li>
<li>幂等性:一次任务执行一遍和执行n遍效果一样,不会重复执行带来意外情况</li>
<li>无需代理不依赖PKI(无需ssl)</li>
<li>可使用任何编程语言写模块</li>
<li>YAML格式,编排任务,丰富的数据结构</li>
<li>较强大的多层解决方案</li>
</ul>
<h3 id="Ansible架构"><a href="#Ansible架构" class="headerlink" title="Ansible架构"></a>Ansible架构</h3><p><img src="https://s1.ax1x.com/2018/06/07/CHJYMF.png" alt="ansible"></p>
<h3 id="Ansible主要组成部分功能说明"><a href="#Ansible主要组成部分功能说明" class="headerlink" title="Ansible主要组成部分功能说明"></a>Ansible主要组成部分功能说明</h3><ul>
<li><strong>PLAYBOOKS</strong>:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YAML文件。</li>
<li><strong>INVENTORY</strong>: Ansible管理主机的清单/etc/anaible/hosts。</li>
<li><strong>MODULES</strong>: Ansible执行命令的功能模块,多数为内置的核心模块,也可自定义,ansible-doc –l 可查看模块。</li>
<li><strong>PLUGINS</strong>: 模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用。</li>
<li><strong>API</strong>:供第三方程序调用的应用程序编程接口。</li>
<li><strong>ANSIBLE</strong>:组合INVENTORY、 API、 MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具。</li>
</ul>
</summary>
<category term="运维自动化工具" scheme="http://www.chenfanlinux.org/categories/%E8%BF%90%E7%BB%B4%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7/"/>
<category term="Ansible" scheme="http://www.chenfanlinux.org/tags/Ansible/"/>
</entry>
<entry>
<title>Python变量进阶</title>
<link href="http://www.chenfanlinux.org/2018/06/06/Python%E5%8F%98%E9%87%8F%E8%BF%9B%E9%98%B6/"/>
<id>http://www.chenfanlinux.org/2018/06/06/Python变量进阶/</id>
<published>2018-06-06T02:27:46.000Z</published>
<updated>2018-06-06T02:45:17.000Z</updated>
<content type="html"><![CDATA[<h2 id="概览"><a href="#概览" class="headerlink" title="概览"></a>概览</h2><ul><li>变量的引用</li><li>可变和不可变类型</li><li>局部变量和全局变量</li></ul><h2 id="变量的引用"><a href="#变量的引用" class="headerlink" title="变量的引用"></a>变量的引用</h2><blockquote><ul><li>变量 和 数据 都是保存在 <strong>内存</strong> 中的</li><li>在 <code>Python</code> 中 <strong>函数 的 参数传递</strong> 以及 <strong>返回值</strong> 都是靠 <strong>引用</strong> 传递的</li></ul></blockquote><h3 id="引用的概念"><a href="#引用的概念" class="headerlink" title="引用的概念"></a>引用的概念</h3><p>在 <code>Python</code> 中</p><ul><li><strong>变量</strong> 和 <strong>数据</strong> 是分开存储的</li><li><strong>数据</strong> 保存在内存中的一个位置</li><li><strong>变量</strong> 中保存着数据在内存中的地址</li><li><strong>变量</strong> 中 <strong>记录数据的地址</strong>,就叫做 <strong>引用</strong></li><li>使用 <code>id()</code> 函数可以查看变量中保存数据所在的 <strong>内存地址</strong></li></ul><blockquote><p>注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是 <strong>修改了数据的引用</strong></p><ul><li>变量 <strong>不再</strong> 对之前的数据引用</li><li>变量 <strong>改为</strong> 对新赋值的数据引用</li></ul></blockquote><a id="more"></a><h3 id="变量引用-的示例"><a href="#变量引用-的示例" class="headerlink" title="变量引用 的示例"></a><code>变量引用</code> 的示例</h3><p>在 <code>Python</code> 中,变量的名字类似于 <strong>便签纸</strong> 贴在 <strong>数据</strong> 上</p><ul><li>定义一个整数变量 <code>a</code>,并且赋值为 <code>1</code></li></ul><table><thead><tr><th style="text-align:center">代码</th><th style="text-align:center">图示</th></tr></thead><tbody><tr><td style="text-align:center">a = 1</td><td style="text-align:center"><img src="https://s1.ax1x.com/2018/06/06/C7oURx.png" alt="004_a1tag"></td></tr></tbody></table><ul><li>将变量 <code>a</code> 赋值为 <code>2</code></li></ul><table><thead><tr><th style="text-align:center">代码</th><th style="text-align:center">图示</th></tr></thead><tbody><tr><td style="text-align:center">a = 2</td><td style="text-align:center"><img src="https://s1.ax1x.com/2018/06/06/C7oaz6.png" alt="005_a2tag"></td></tr></tbody></table><ul><li>定义一个整数变量 <code>b</code>,并且将变量 <code>a</code> 的值赋值给 <code>b</code></li></ul><table><thead><tr><th style="text-align:center">代码</th><th style="text-align:center">图示</th></tr></thead><tbody><tr><td style="text-align:center">b = a</td><td style="text-align:center"><img src="https://s1.ax1x.com/2018/06/06/C7owQK.png" alt="006_ab2tag"></td></tr></tbody></table><blockquote><p>变量 <code>b</code> 是第 2 个贴在数字 <code>2</code> 上的标签</p></blockquote><h3 id="函数的参数和返回值的传递"><a href="#函数的参数和返回值的传递" class="headerlink" title="函数的参数和返回值的传递"></a>函数的参数和返回值的传递</h3><p>在 <code>Python</code> 中,函数的 <strong>实参</strong>/<strong>返回值</strong> 都是是靠 <strong>引用</strong> 来传递来的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span><span class="params">(num)</span>:</span></span><br><span class="line"></span><br><span class="line"> print(<span class="string">"-"</span> * <span class="number">50</span>)</span><br><span class="line"> print(<span class="string">"%d 在函数内的内存地址是 %x"</span> % (num, id(num)))</span><br><span class="line"></span><br><span class="line"> result = <span class="number">100</span></span><br><span class="line"></span><br><span class="line"> print(<span class="string">"返回值 %d 在内存中的地址是 %x"</span> % (result, id(result)))</span><br><span class="line"> print(<span class="string">"-"</span> * <span class="number">50</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line">a = <span class="number">10</span></span><br><span class="line">print(<span class="string">"调用函数前 内存地址是 %x"</span> % id(a))</span><br><span class="line"></span><br><span class="line">r = test(a)</span><br><span class="line"></span><br><span class="line">print(<span class="string">"调用函数后 实参内存地址是 %x"</span> % id(a))</span><br><span class="line">print(<span class="string">"调用函数后 返回值内存地址是 %x"</span> % id(r))</span><br></pre></td></tr></table></figure><h2 id="可变和不可变类型"><a href="#可变和不可变类型" class="headerlink" title="可变和不可变类型"></a>可变和不可变类型</h2><ul><li><p><strong>不可变类型</strong>,内存中的数据不允许被修改:</p><ul><li>数字类型 <code>int</code>, <code>bool</code>, <code>float</code>, <code>complex</code>, <code>long(2.x)</code></li><li>字符串 <code>str</code></li><li>元组 <code>tuple</code></li></ul></li><li><p><strong>可变类型</strong>,内存中的数据可以被修改:</p><ul><li>列表 <code>list</code></li><li>字典 <code>dict</code></li></ul></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="number">1</span></span><br><span class="line">a = <span class="string">"hello"</span></span><br><span class="line">a = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line">a = [<span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>]</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">demo_list = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"></span><br><span class="line">print(<span class="string">"定义列表后的内存地址 %d"</span> % id(demo_list))</span><br><span class="line"></span><br><span class="line">demo_list.append(<span class="number">999</span>)</span><br><span class="line">demo_list.pop(<span class="number">0</span>)</span><br><span class="line">demo_list.remove(<span class="number">2</span>)</span><br><span class="line">demo_list[<span class="number">0</span>] = <span class="number">10</span></span><br><span class="line"></span><br><span class="line">print(<span class="string">"修改数据后的内存地址 %d"</span> % id(demo_list))</span><br><span class="line"></span><br><span class="line">demo_dict = {<span class="string">"name"</span>: <span class="string">"小明"</span>}</span><br><span class="line"></span><br><span class="line">print(<span class="string">"定义字典后的内存地址 %d"</span> % id(demo_dict))</span><br><span class="line"></span><br><span class="line">demo_dict[<span class="string">"age"</span>] = <span class="number">18</span></span><br><span class="line">demo_dict.pop(<span class="string">"name"</span>)</span><br><span class="line">demo_dict[<span class="string">"name"</span>] = <span class="string">"老王"</span></span><br><span class="line"></span><br><span class="line">print(<span class="string">"修改数据后的内存地址 %d"</span> % id(demo_dict))</span><br></pre></td></tr></table></figure><blockquote><p>注意:字典的 <code>key</code> <strong>只能使用不可变类型的数据</strong></p></blockquote><p><strong>注意</strong></p><ol><li><strong>可变类型</strong>的数据变化,是通过 <strong>方法</strong> 来实现的</li><li>如果给一个可变类型的变量,赋值了一个新的数据,<strong>引用会修改</strong><ul><li>变量 <strong>不再</strong> 对之前的数据引用</li><li>变量 <strong>改为</strong> 对新赋值的数据引用</li></ul></li></ol><h3 id="哈希-hash"><a href="#哈希-hash" class="headerlink" title="哈希 (hash)"></a>哈希 <code>(hash)</code></h3><ul><li><code>Python</code> 中内置有一个名字叫做 <code>hash(o)</code> 的函数<ul><li>接收一个 <strong>不可变类型</strong> 的数据作为 <strong>参数</strong></li><li><strong>返回</strong> 结果是一个 <strong>整数</strong></li></ul></li><li><code>哈希</code> 是一种 <strong>算法</strong>,其作用就是提取数据的 <strong>特征码(指纹)</strong><ul><li><strong>相同的内容</strong> 得到 <strong>相同的结果</strong></li><li><strong>不同的内容</strong> 得到 <strong>不同的结果</strong></li></ul></li><li>在 <code>Python</code> 中,设置字典的 <strong>键值对</strong> 时,会首先对 <code>key</code> 进行 <code>hash</code> 已决定如何在内存中保存字典的数据,以方便 <strong>后续</strong> 对字典的操作:<strong>增、删、改、查</strong><ul><li>键值对的 <code>key</code> 必须是不可变类型数据</li><li>键值对的 <code>value</code> 可以是任意类型的数据</li></ul></li></ul><h2 id="局部变量和全局变量"><a href="#局部变量和全局变量" class="headerlink" title="局部变量和全局变量"></a>局部变量和全局变量</h2><ul><li><strong>局部变量</strong> 是在 <strong>函数内部</strong> 定义的变量,<strong>只能在函数内部使用</strong></li><li><strong>全局变量</strong> 是在 <strong>函数外部定义</strong> 的变量(没有定义在某一个函数内),<strong>所有函数</strong> 内部 <strong>都可以使用这个变量</strong></li></ul><blockquote><p>提示:在其他的开发语言中,大多 <strong>不推荐使用全局变量</strong> —— 可变范围太大,导致程序不好维护!</p></blockquote><h3 id="局部变量"><a href="#局部变量" class="headerlink" title="局部变量"></a>局部变量</h3><ul><li><strong>局部变量</strong> 是在 <strong>函数内部</strong> 定义的变量,<strong>只能在函数内部使用</strong></li><li>函数执行结束后,<strong>函数内部的局部变量,会被系统回收</strong></li><li>不同的函数,可以定义相同的名字的局部变量,但是 <strong>彼此之间</strong> 不会产生影响</li></ul><h4 id="局部变量的作用"><a href="#局部变量的作用" class="headerlink" title="局部变量的作用"></a>局部变量的作用</h4><ul><li>在函数内部使用,<strong>临时</strong> 保存 <strong>函数内部需要使用的数据</strong></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo1</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> num = <span class="number">10</span></span><br><span class="line"></span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line"> num = <span class="number">20</span></span><br><span class="line"></span><br><span class="line"> print(<span class="string">"修改后 %d"</span> % num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo2</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> num = <span class="number">100</span></span><br><span class="line"></span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line">demo1()</span><br><span class="line">demo2()</span><br><span class="line"></span><br><span class="line">print(<span class="string">"over"</span>)</span><br></pre></td></tr></table></figure><h4 id="局部变量的生命周期"><a href="#局部变量的生命周期" class="headerlink" title="局部变量的生命周期"></a>局部变量的生命周期</h4><ul><li>所谓 <strong>生命周期</strong> 就是变量从 <strong>被创建</strong> 到 <strong>被系统回收</strong> 的过程</li><li><strong>局部变量</strong> 在 <strong>函数执行时</strong> 才会被创建</li><li><strong>函数执行结束后</strong> 局部变量 <strong>被系统回收</strong></li><li><strong>局部变量在生命周期</strong> 内,可以用来存储 <strong>函数内部临时使用到的数据</strong></li></ul><h3 id="全局变量"><a href="#全局变量" class="headerlink" title="全局变量"></a>全局变量</h3><ul><li><strong>全局变量</strong> 是在 <strong>函数外部定义</strong> 的变量,所有函数内部都可以使用这个变量</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 定义一个全局变量</span></span><br><span class="line">num = <span class="number">10</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo1</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo2</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line">demo1()</span><br><span class="line">demo2()</span><br><span class="line"></span><br><span class="line">print(<span class="string">"over"</span>)</span><br></pre></td></tr></table></figure><p><strong>注意</strong>:函数执行时,<strong>需要处理变量时</strong> 会:</p><ol><li><strong>首先</strong> 查找 <strong>函数内部</strong> 是否存在 <strong>指定名称 的局部变量</strong>,<strong>如果有,直接使用</strong></li><li>如果没有,查找 <strong>函数外部</strong> 是否存在 <strong>指定名称 的全局变量</strong>,<strong>如果有,直接使用</strong></li><li>如果还没有,程序报错!</li></ol><h4 id="1-函数不能直接修改-全局变量的引用"><a href="#1-函数不能直接修改-全局变量的引用" class="headerlink" title="1) 函数不能直接修改 全局变量的引用"></a>1) 函数不能直接修改 <code>全局变量的引用</code></h4><ul><li><strong>全局变量</strong> 是在 <strong>函数外部定义</strong> 的变量(没有定义在某一个函数内),<strong>所有函数</strong> 内部 <strong>都可以使用这个变量</strong></li></ul><blockquote><p>提示:在其他的开发语言中,大多 <strong>不推荐使用全局变量</strong> —— 可变范围太大,导致程序不好维护!</p></blockquote><ul><li>在函数内部,可以 <strong>通过全局变量的引用获取对应的数据</strong></li><li>但是,<strong>不允许直接修改全局变量的引用</strong> —— 使用赋值语句修改全局变量的值</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">num = <span class="number">10</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo1</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> print(<span class="string">"demo1"</span> + <span class="string">"-"</span> * <span class="number">50</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 只是定义了一个局部变量,不会修改到全局变量,只是变量名相同而已</span></span><br><span class="line"> num = <span class="number">100</span></span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo2</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> print(<span class="string">"demo2"</span> + <span class="string">"-"</span> * <span class="number">50</span>)</span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line">demo1()</span><br><span class="line">demo2()</span><br><span class="line"></span><br><span class="line">print(<span class="string">"over"</span>)</span><br></pre></td></tr></table></figure><blockquote><p>注意:只是在函数内部定义了一个局部变量而已,只是变量名相同 —— 在函数内部不能直接修改全局变量的值</p></blockquote><h4 id="2-在函数内部修改全局变量的值"><a href="#2-在函数内部修改全局变量的值" class="headerlink" title="2) 在函数内部修改全局变量的值"></a>2) 在函数内部修改全局变量的值</h4><ul><li>如果在函数中需要修改全局变量,需要使用 <code>global</code> 进行声明</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">num = <span class="number">10</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo1</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> print(<span class="string">"demo1"</span> + <span class="string">"-"</span> * <span class="number">50</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># global 关键字,告诉 Python 解释器 num 是一个全局变量</span></span><br><span class="line"> <span class="keyword">global</span> num</span><br><span class="line"> <span class="comment"># 只是定义了一个局部变量,不会修改到全局变量,只是变量名相同而已</span></span><br><span class="line"> num = <span class="number">100</span></span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo2</span><span class="params">()</span>:</span></span><br><span class="line"></span><br><span class="line"> print(<span class="string">"demo2"</span> + <span class="string">"-"</span> * <span class="number">50</span>)</span><br><span class="line"> print(num)</span><br><span class="line"></span><br><span class="line">demo1()</span><br><span class="line">demo2()</span><br><span class="line"></span><br><span class="line">print(<span class="string">"over"</span>)</span><br></pre></td></tr></table></figure><h4 id="3-全局变量定义的位置"><a href="#3-全局变量定义的位置" class="headerlink" title="3) 全局变量定义的位置"></a>3) 全局变量定义的位置</h4><ul><li>为了保证所有的函数都能够正确使用到全局变量,应该 <strong>将全局变量定义在其他函数的上方</strong></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="number">10</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">demo</span><span class="params">()</span>:</span></span><br><span class="line"> print(<span class="string">"%d"</span> % a)</span><br><span class="line"> print(<span class="string">"%d"</span> % b)</span><br><span class="line"> print(<span class="string">"%d"</span> % c)</span><br><span class="line"></span><br><span class="line">b = <span class="number">20</span></span><br><span class="line">demo()</span><br><span class="line">c = <span class="number">30</span></span><br></pre></td></tr></table></figure><p><strong>注意</strong></p><ul><li>由于全局变量 c,是在调用函数之后,才定义的,在执行函数时,变量还没有定义,所以程序会报错!</li></ul><p><strong>代码结构示意图如下</strong></p><p><img src="https://s1.ax1x.com/2018/06/06/C7oree.png" alt="001_代码结构示意图-w240"></p><h4 id="4-全局变量命名的建议"><a href="#4-全局变量命名的建议" class="headerlink" title="4) 全局变量命名的建议"></a>4) 全局变量命名的建议</h4><ul><li>为了避免局部变量和全局变量出现混淆,在定义全局变量时,有些公司会有一些开发要求,例如:</li><li>全局变量名前应该增加 <code>g_</code> 或者 <code>gl_</code> 的前缀</li></ul><blockquote><p>提示:具体的要求格式,各公司要求可能会有些差异</p></blockquote>]]></content>
<summary type="html">
<h2 id="概览"><a href="#概览" class="headerlink" title="概览"></a>概览</h2><ul>
<li>变量的引用</li>
<li>可变和不可变类型</li>
<li>局部变量和全局变量</li>
</ul>
<h2 id="变量的引用"><a href="#变量的引用" class="headerlink" title="变量的引用"></a>变量的引用</h2><blockquote>
<ul>
<li>变量 和 数据 都是保存在 <strong>内存</strong> 中的</li>
<li>在 <code>Python</code> 中 <strong>函数 的 参数传递</strong> 以及 <strong>返回值</strong> 都是靠 <strong>引用</strong> 传递的</li>
</ul>
</blockquote>
<h3 id="引用的概念"><a href="#引用的概念" class="headerlink" title="引用的概念"></a>引用的概念</h3><p>在 <code>Python</code> 中</p>
<ul>
<li><strong>变量</strong> 和 <strong>数据</strong> 是分开存储的</li>
<li><strong>数据</strong> 保存在内存中的一个位置</li>
<li><strong>变量</strong> 中保存着数据在内存中的地址</li>
<li><strong>变量</strong> 中 <strong>记录数据的地址</strong>,就叫做 <strong>引用</strong></li>
<li>使用 <code>id()</code> 函数可以查看变量中保存数据所在的 <strong>内存地址</strong></li>
</ul>
<blockquote>
<p>注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是 <strong>修改了数据的引用</strong></p>
<ul>
<li>变量 <strong>不再</strong> 对之前的数据引用</li>
<li>变量 <strong>改为</strong> 对新赋值的数据引用</li>
</ul>
</blockquote>
</summary>
<category term="python基础知识" scheme="http://www.chenfanlinux.org/categories/python%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/"/>
<category term="python变量" scheme="http://www.chenfanlinux.org/tags/python%E5%8F%98%E9%87%8F/"/>
</entry>
<entry>
<title>Python操作Redis</title>
<link href="http://www.chenfanlinux.org/2018/06/04/Python%E6%93%8D%E4%BD%9CRedis/"/>
<id>http://www.chenfanlinux.org/2018/06/04/Python操作Redis/</id>
<published>2018-06-04T09:36:30.000Z</published>
<updated>2018-06-04T09:52:21.000Z</updated>
<content type="html"><![CDATA[<h2 id="Redis-简介"><a href="#Redis-简介" class="headerlink" title="Redis 简介"></a>Redis 简介</h2><h3 id="Redis-特点"><a href="#Redis-特点" class="headerlink" title="Redis 特点"></a>Redis 特点</h3><blockquote><p>Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。</p></blockquote><p>Redis 与其他 key - value 缓存产品有以下三个特点:</p><ul><li>Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。</li><li>Redis不仅仅支持简单的key-value类型的数据,同时还提供string, list,set,zset,hash等数据结构的存储。</li><li>Redis支持数据的备份,即master-slave模式的数据备份。</li></ul><h3 id="Redis-优势"><a href="#Redis-优势" class="headerlink" title="Redis 优势"></a>Redis 优势</h3><ul><li>性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。</li><li>丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。</li><li>原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。</li><li>丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。</li></ul><a id="more"></a><h3 id="Redis与其他key-value存储有什么不同?"><a href="#Redis与其他key-value存储有什么不同?" class="headerlink" title="Redis与其他key-value存储有什么不同?"></a>Redis与其他key-value存储有什么不同?</h3><ul><li>Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。</li><li>Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。</li></ul><h2 id="安装Redis"><a href="#安装Redis" class="headerlink" title="安装Redis"></a>安装Redis</h2><h3 id="windows下安装Redis"><a href="#windows下安装Redis" class="headerlink" title="windows下安装Redis"></a>windows下安装Redis</h3><p><strong>下载地址:</strong><a href="https://github.com/MSOpenTech/redis/releases" target="_blank" rel="noopener">https://github.com/MSOpenTech/redis/releases</a></p><p>Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 <strong>Redis-x64-xxx.zip</strong>压缩包到 F盘,解压后,将文件夹重新命名为 <strong>redis</strong> 。</p><p><img src="http://www.runoob.com/wp-content/uploads/2014/11/3B8D633F-14CE-42E3-B174-FCCD48B11FF3.jpg" alt="redis"></p><p>写一个启动redis服务的redis.bat文件,双击即可以启动服务,方便服务的管理。</p><p>redis.bat文件内容如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">f:</span><br><span class="line"><span class="built_in">cd</span> redis\</span><br><span class="line">redis-server.exe redis.windows.conf</span><br></pre></td></tr></table></figure><p>切换到redis目录下运行 <code>redis-cli.exe -h 127.0.0.1 -p 6379</code>即可以开启客户端。</p><h3 id="linux下安装Redis"><a href="#linux下安装Redis" class="headerlink" title="linux下安装Redis"></a>linux下安装Redis</h3><p><strong>下载地址:</strong><a href="http://redis.io/download" target="_blank" rel="noopener">http://redis.io/download</a>,下载最新稳定版本。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ wget http://download.redis.io/releases/redis-2.8.17.tar.gz</span><br><span class="line">$ tar xzf redis-2.8.17.tar.gz</span><br><span class="line">$ <span class="built_in">cd</span> redis-2.8.17</span><br><span class="line">$ make</span><br></pre></td></tr></table></figure><p>make完后 redis-2.8.17目录下会出现编译后的redis服务程序redis-server,还有用于测试的客户端程序redis-cli,两个程序位于安装目录 src 目录下:</p><p>下面启动redis服务:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">cd</span> src</span><br><span class="line">$ ./redis-server</span><br></pre></td></tr></table></figure><p>注意这种方式启动redis 使用的是默认配置。也可以通过启动参数告诉redis使用指定配置文件使用下面命令启动。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">cd</span> src</span><br><span class="line">$ ./redis-server redis.conf</span><br></pre></td></tr></table></figure><p>redis.conf是一个默认的配置文件。我们可以根据需要使用自己的配置文件。启动redis服务进程后,就可以使用测试客户端程序redis-cli和redis服务交互了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">cd</span> src</span><br><span class="line">$ ./redis-cli</span><br><span class="line">redis> <span class="built_in">set</span> foo bar</span><br><span class="line">OK</span><br><span class="line">redis> get foo</span><br><span class="line"><span class="string">"bar"</span></span><br></pre></td></tr></table></figure><h2 id="Redis数据类型"><a href="#Redis数据类型" class="headerlink" title="Redis数据类型"></a>Redis数据类型</h2><blockquote><p>Redis支持五种数据类型:<code>string</code>(字符串),<code>hash</code>(哈希),<code>list</code>(列表),<code>set</code>(集合)及<code>zset</code>(sorted set:有序集合)。</p></blockquote><h3 id="String(字符串)操作"><a href="#String(字符串)操作" class="headerlink" title="String(字符串)操作"></a><code>String</code>(字符串)操作</h3><p>在Redis中设置值,不存在则创建,存在则修改</p><p><code>set(name, value, ex=None, px=None, nx=False, xx=False)</code> </p><table><thead><tr><th>参数</th><th>意义</th></tr></thead><tbody><tr><td>ex</td><td>过期时间(秒)</td></tr><tr><td>px</td><td>过期时间(毫秒)</td></tr><tr><td>nx</td><td>如果设置为True,则只有name不存在时,当前set操作才执行,同setnx(name, value)</td></tr><tr><td>xx</td><td>如果设置为True,则只有name存在时,当前set操作才执行</td></tr></tbody></table><p><code>setex(name, value, time)</code> 设置过期时间(秒)</p><p><code>psetex(name, time_ms, value)</code> 设置过期时间(豪秒)</p><p><code>mset(name1='***', name2='***',......)</code> 批量设置值</p><p><code>get(name)</code> 获取值</p><p><code>mget(*keys)</code> 批量获取值</p><p><code>getset(name, value)</code> 设置新值,打印原值</p><p><code>getrange(key, start, end)</code> 获取值,并切片,返回切片后的结果</p><p><code>setrange(name, offset, value)</code> 修改字符串内容,从指定字符串索引开始向后替换,如果新值太长时,则向后添加</p><p><code>setbit(name, offset, value)</code> 对二进制表示位进行操作</p><p><code>getbit(name, offset)</code> 获取name对应值的二进制中某位的值(0或1)</p><p><code>bitcount(key, start=None, end=None)</code> 获取对应二进制中1的个数</p><p><code>strlen(name)</code> 返回name对应值的字节长度(一个汉字3个字节)</p><p><code>incr(name, amount=1)</code> 自增name对应的值,当name不存在时,则创建name=amount,否则,则自增,amount为自增数(整数)</p><p><code>incrbyfloat(name, amount=1.0)</code> 类似<code>incr()</code>自增,amount为自增数(浮点数)</p><p><code>decr(name, amount=1)</code> 自减name对应的值,当name不存在时,则创建name=amount,否则,则自减,amount为自增数(整数)</p><p><code>append(name, value)</code> 在name对应的值后面追加内容</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">import</span> redis</span><br><span class="line"><span class="meta">>>> </span>r = redis.Redis(host=<span class="string">'127.0.0.1'</span>, port=<span class="number">6379</span>)</span><br><span class="line">r.set(<span class="string">'key1'</span>,<span class="string">'value1'</span>)</span><br></pre></td></tr></table></figure><h3 id="Hash(哈希)操作"><a href="#Hash(哈希)操作" class="headerlink" title="Hash(哈希)操作"></a><code>Hash</code>(哈希)操作</h3><blockquote><p>redis中的Hash 在内存中类似于一个name对应一个dic来存储</p></blockquote><p><code>hset(name, key, value)</code> name对应的hash中设置一个键值对。不存在,则创建,否则,修改。</p><p><code>hget(name,key)</code> 在name对应的hash中根据key获取value</p><p><code>hgetall(name)</code> 获取name对应hash的所有键值</p><p><code>hmset(name, dict)</code> 在name对应的hash中批量设置键值对</p><p><code>hmget(name, keys)</code> 在name对应的hash中获取多个key的值</p><p><code>hlen(name)</code> 获取hash中键值对的个数</p><p><code>hkeys(name)</code> 获取hash中所有的key的值</p><p><code>hvals(name)</code> 获取hash中所有的value的值</p><p><code>hexists(name, key)</code> 检查name对应的hash是否存在当前传入的key</p><p><code>hdel(name,*keys)</code> 删除指定name对应的key所在的键值对</p><p><code>hincrby(name, key, amount)</code> 自增hash中key对应的值,不存在则创建key=amount(amount为整数)</p><p><code>hincrbyfloat(name, key, amount)</code> 自增hash中key对应的值,不存在则创建key=amount(amount为浮点数)</p><p><code>hscan(name, cursor=0, match=None, count=None)</code></p><p><code>hscan_iter(name, match=None, count=None)</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">import</span> redis</span><br><span class="line"><span class="meta">>>> </span>r.hset(<span class="string">'hkey'</span>,<span class="string">'key1'</span>,<span class="string">'value1'</span>)</span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="meta">>>> </span>r.hget(<span class="string">'hkey'</span>,<span class="string">'key1'</span>)</span><br><span class="line"><span class="string">b'value1</span></span><br></pre></td></tr></table></figure><h3 id="List(列表)操作"><a href="#List(列表)操作" class="headerlink" title="List(列表)操作"></a><code>List</code>(列表)操作</h3><blockquote><p>redis中的List在在内存中按照一个name对应一个List来存储</p></blockquote><p><code>lpush(name,*values)</code> 在name对应的list中添加元素,每个新的元素都添加到列表的最左边</p><p><code>rpush(name,*values)</code> 同<code>lpush</code>,但每个新的元素都添加到列表的最右边</p><p><code>lpushx(name,value)</code> 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边</p><p><code>rpushx(name,value)</code> 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最右边</p><p><code>llen(name)</code> name对应的list元素的个数</p><p><code>linsert(name, where, refvalue, value))</code> 在name对应的列表的某一个值前或后插入一个新值</p><table><thead><tr><th>参数</th><th>意义</th></tr></thead><tbody><tr><td>name</td><td>redis的name</td></tr><tr><td>where</td><td>BEFORE(前)或AFTER(后)</td></tr><tr><td>refvalue</td><td>列表内的值</td></tr><tr><td>value</td><td>要插入的数据</td></tr></tbody></table><p><code>r.lset(name, index, value)</code> 对list中的某一个索引位置重新赋值</p><p><code>lrem(name, value, num)</code> 删除name对应的list中的指定值</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">name --- redis的name</span><br><span class="line">value --- 要删除的值</span><br><span class="line">num --- num为0,表示删除列表中所有的指定值;</span><br><span class="line"> num为n,表示从前到后删除n个;</span><br><span class="line"> num为-n:从后向前删除n个</span><br></pre></td></tr></table></figure><p><code>lpop(name)</code> 移除列表的左侧第一个元素,返回值是移除的元素</p><p><code>lindex(name, index)</code> 根据索引获取列表内元素</p><p><code>lrange(name, start, end)</code> 分片获取元素</p><p><code>ltrim(name, start, end)</code> 移除列表内没有在该索引之内的值</p><p><code>rpoplpush(src, dst)</code> # 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边,src要取数据的列表,dst要添加数据的列表</p><p><code>brpoplpush(src, dst, timeout=0)</code> 同rpoplpush,多了个timeout, timeout:取数据的列表没元素后的阻塞时间,0为一直阻塞</p><p><code>blpop(keys, timeout)</code> 将多个列表排列,按照从左到右去移除各个列表内的元素;timeout: 超时时间,获取完所有列表的元素之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞</p><p><code>brpop(keys, timeout)</code> 同blpop,将多个列表排列,按照从右像左去移除各个列表内的元素</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>r.lpush(<span class="string">'rlist'</span>,(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>))</span><br><span class="line"><span class="number">1</span></span><br></pre></td></tr></table></figure><h3 id="Set(集合)操作"><a href="#Set(集合)操作" class="headerlink" title="Set(集合)操作"></a><code>Set</code>(集合)操作</h3><blockquote><p>Set集合就是不允许重复的列表</p></blockquote><p><code>sadd(name,*values)</code> 给name对应的集合中添加元素</p><p><code>smembers(name)</code> 获取name对应的集合的所有成员</p><p><code>scard(name)</code> 获取name对应的集合中的元素个数</p><p><code>sdiff(name, *names)</code> 在第一个name对应的集合中且不在其他name对应的集合的元素集合</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> redis,time</span><br><span class="line"></span><br><span class="line">r = redis.Redis(host=<span class="string">'127.0.0.1'</span>, port=<span class="number">6379</span>)</span><br><span class="line">r.sadd(<span class="string">"name"</span>,<span class="string">"a"</span>,<span class="string">"b"</span>)</span><br><span class="line">r.sadd(<span class="string">"name1"</span>,<span class="string">"b"</span>,<span class="string">"c"</span>)</span><br><span class="line">r.sadd(<span class="string">"name2"</span>,<span class="string">"b"</span>,<span class="string">"c"</span>,<span class="string">"d"</span>)</span><br><span class="line">print(r.sdiff(<span class="string">"name"</span>,<span class="string">"name1"</span>,<span class="string">"name2"</span>))<span class="comment">#输出:{a}</span></span><br></pre></td></tr></table></figure><p><code>sdiffstore(dest, name, *names)</code> 相当于把<code>sdiff</code>获取的值加入到dest对应的集合中</p><p><code>sinter(*names)</code> 获取多个name对应集合的交集</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> redis,time</span><br><span class="line"></span><br><span class="line">r = redis.Redis(host=<span class="string">'127.0.0.1'</span>, port=<span class="number">6379</span>)</span><br><span class="line">r.sadd(<span class="string">"name"</span>,<span class="string">"a"</span>,<span class="string">"b"</span>)</span><br><span class="line">r.sadd(<span class="string">"name1"</span>,<span class="string">"b"</span>,<span class="string">"c"</span>)</span><br><span class="line">r.sadd(<span class="string">"name2"</span>,<span class="string">"b"</span>,<span class="string">"c"</span>,<span class="string">"d"</span>)</span><br><span class="line">print(r.sinter(<span class="string">"name"</span>,<span class="string">"name1"</span>,<span class="string">"name2"</span>))<span class="comment">#输出:{b}</span></span><br></pre></td></tr></table></figure><p><code>sinterstore(dest, name, *names)</code> 获取多个name对应集合的交集,再讲其加入到dest对应的集合中;相当于把<code>sinter</code>获取的值加入到dest对应的集合中</p><p><code>sismember(name, value)</code> 检查value是否是name对应的集合内的元素</p><p><code>smove(src, dst, value)</code> 将某个元素从一个集合中移动到另外一个集合</p><p><code>spop(name)</code> 从集合的右侧移除一个元素,并将其返回</p><p><code>srandmember(name, numbers)</code> 从name对应的集合中随机获取numbers个元素</p><p><code>srem(name, *values)</code> 删除name对应的集合中的某些值</p><p><code>sunion(*names)</code> 获取多个name对应的集合的并集</p><p><code>sunionstore(dest,*names)</code> 获取多个name对应的集合的并集,并将结果保存到dest对应的集合中</p><h3 id="zset(有序集合)"><a href="#zset(有序集合)" class="headerlink" title="zset(有序集合)"></a><code>zset</code>(有序集合)</h3><blockquote><p>在集合的基础上,为每元素排序,元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序 。</p></blockquote><p><code>zadd(name, *args, **kwargs)</code> 在name对应的有序集合中添加元素</p><p><code>zcard(name)</code> 获取有序集合内元素的数量</p><p><code>zcount(name, min, max)</code> 获取有序集合中分数在min~max之间的个数</p><p><code>zincrby(name, value, amount)</code> 自增有序集合内value对应的分数</p><p><code>zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)</code> 按照索引范围获取name对应的有序集合的元素</p><table><thead><tr><th>参数</th><th>意义</th></tr></thead><tbody><tr><td>name</td><td>redis的name</td></tr><tr><td>start</td><td>有序集合索引起始位置</td></tr><tr><td>end</td><td>有序集合索引结束位置</td></tr><tr><td>desc</td><td>排序规则,默认按照分数从小到大排序</td></tr><tr><td>withscores</td><td>是否获取元素的分数,默认只获取元素的值</td></tr><tr><td>score_cast_func</td><td>对分数进行数据转换的函数</td></tr></tbody></table><p><code>zrevrange(name, start, end, withscores=False, score_cast_func=float)</code> 同<code>zrange</code>,集合是从大到小排序的</p><p><code>zrank(name, value)</code> 获取value值在name对应的有序集合中的排行位置(从0开始)</p><p><code>zrevrank(name, value)</code> 同<code>zrank</code>,集合是从大到小排序的</p><p><code>zscore(name, value)</code> 获取name对应有序集合中 value 对应的分数</p><p><code>zrem(name, *values)</code> 删除name对应的有序集合中值是values的成员</p><p><code>zremrangebyrank(name, min, max)</code> 根据排行范围删除</p><p><code>zremrangebyscore(name, min, max)</code> 根据分数范围删除</p><p><code>zinterstore(dest, *keys, aggregate=None)</code> 获取两个有序集合的交集并放入dest集合,如果遇到相同值不同分数,则按照aggregate进行操作。aggregate的值为: SUM MIN MAX</p><p><code>zunionstore(dest, keys, aggregate=None)</code> 获取两个有序集合的并集并放入dest集合,其他同<code>zinterstore</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>r.zadd(<span class="string">'zset1'</span>,a=<span class="number">2</span>,b=<span class="number">3</span>,c=<span class="number">4</span>)</span><br><span class="line"><span class="number">3</span></span><br></pre></td></tr></table></figure><h2 id="其他常用操作"><a href="#其他常用操作" class="headerlink" title="其他常用操作"></a>其他常用操作</h2><p><code>delete(*names)</code> 根据name删除redis中的任意数据类型</p><p><code>exists(name)</code> 检测redis的name是否存在</p><p><code>keys(pattern='*')</code> 根据* ?等通配符匹配获取redis的name</p><p><code>expire(name ,time)</code> 为某个name设置超时时间</p><p><code>rename(src, dst)</code> 重命名</p><p><code>move(name, db))</code> 将redis的某个值移动到指定的db下</p><p><code>randomkey()</code> 随机获取一个redis的name(不删除)</p><p><code>type(name)</code> 获取name对应值的类型</p>]]></content>
<summary type="html">
<h2 id="Redis-简介"><a href="#Redis-简介" class="headerlink" title="Redis 简介"></a>Redis 简介</h2><h3 id="Redis-特点"><a href="#Redis-特点" class="headerlink" title="Redis 特点"></a>Redis 特点</h3><blockquote>
<p>Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。</p>
</blockquote>
<p>Redis 与其他 key - value 缓存产品有以下三个特点:</p>
<ul>
<li>Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。</li>
<li>Redis不仅仅支持简单的key-value类型的数据,同时还提供string, list,set,zset,hash等数据结构的存储。</li>
<li>Redis支持数据的备份,即master-slave模式的数据备份。</li>
</ul>
<h3 id="Redis-优势"><a href="#Redis-优势" class="headerlink" title="Redis 优势"></a>Redis 优势</h3><ul>
<li>性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。</li>
<li>丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。</li>
<li>原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。</li>
<li>丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。</li>
</ul>
</summary>
<category term="NoSQL" scheme="http://www.chenfanlinux.org/categories/NoSQL/"/>
<category term="redis" scheme="http://www.chenfanlinux.org/tags/redis/"/>
<category term="python" scheme="http://www.chenfanlinux.org/tags/python/"/>
</entry>
<entry>
<title>Python内建函数</title>
<link href="http://www.chenfanlinux.org/2018/06/03/Python%E5%86%85%E5%BB%BA%E5%87%BD%E6%95%B0/"/>
<id>http://www.chenfanlinux.org/2018/06/03/Python内建函数/</id>
<published>2018-06-03T05:53:40.000Z</published>
<updated>2018-06-03T06:12:36.000Z</updated>
<content type="html"><![CDATA[<h2 id="内建函数引言"><a href="#内建函数引言" class="headerlink" title="内建函数引言"></a>内建函数引言</h2><blockquote><p>Python内建函数按分类可以分为系统内建函数和内置对象(字符串,列表,字典,set,文件对象)的方法,下面我们将带您认识系统内建函数和内置数据对象的方法。</p></blockquote><ul><li>系统内建函数</li><li>内置对象方法<ul><li>str字符</li><li>list列表</li><li>tuple元组</li><li>dict字典</li><li>set集合</li></ul></li></ul><h2 id="系统内建函数"><a href="#系统内建函数" class="headerlink" title="系统内建函数"></a>系统内建函数</h2><blockquote><p>查看官方文档: <a href="https://docs.python.org/3/library/functions.html" target="_blank" rel="noopener">python系统内建函数</a></p></blockquote><p><img src="https://s1.ax1x.com/2018/05/19/Cc0kKP.png" alt="Python系统内建函数图"></p><h3 id="dir"><a href="#dir" class="headerlink" title="dir()"></a>dir()</h3><ul><li><p>作用:返回一个对象中中的所有方法 </p></li><li><p>使用方法:dir([object]) </p></li><li><p>返回值:list of strings </p></li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dir(str) <span class="comment"># 查找str类型对象所对应的方法</span></span><br><span class="line">[<span class="string">'__add__'</span>, <span class="string">'__class__'</span>, <span class="string">'__contains__'</span>, <span class="string">'__delattr__'</span>, <span class="string">'__dir__'</span>, <span class="string">'__doc__'</span>, <span class="string">'__eq__'</span>, <span class="string">'__format__'</span>, <span class="string">'__ge__'</span>, <span class="string">'__getattribute__'</span>, <span class="string">'__getitem__'</span>, <span class="string">'__getnewargs__'</span>, <span class="string">'__gt__'</span>, <span class="string">'__hash__'</span>, <span class="string">'__init__'</span>, <span class="string">'__iter__'</span>, <span class="string">'__le__'</span>, <span class="string">'__len__'</span>, <span class="string">'__lt__'</span>, <span class="string">'__mod__'</span>, <span class="string">'__mul__'</span>, <span class="string">'__ne__'</span>, <span class="string">'__new__'</span>, <span class="string">'__reduce__'</span>, <span class="string">'__reduce_ex__'</span>, <span class="string">'__repr__'</span>, <span class="string">'__rmod__'</span>, <span class="string">'__rmul__'</span>, <span class="string">'__setattr__'</span>, <span class="string">'__sizeof__'</span>, <span class="string">'__str__'</span>, <span class="string">'__subclasshook__'</span>, <span class="string">'capitalize'</span>, <span class="string">'casefold'</span>, <span class="string">'center'</span>, <span class="string">'count'</span>, <span class="string">'encode'</span>, <span class="string">'endswith'</span>, <span class="string">'expandtabs'</span>, <span class="string">'find'</span>, <span class="string">'format'</span>, <span class="string">'format_map'</span>, <span class="string">'index'</span>, <span class="string">'isalnum'</span>, <span class="string">'isalpha'</span>, <span class="string">'isdecimal'</span>, <span class="string">'isdigit'</span>, <span class="string">'isidentifier'</span>, <span class="string">'islower'</span>, <span class="string">'isnumeric'</span>, <span class="string">'isprintable'</span>, <span class="string">'isspace'</span>, <span class="string">'istitle'</span>, <span class="string">'isupper'</span>, <span class="string">'join'</span>, <span class="string">'ljust'</span>, <span class="string">'lower'</span>, <span class="string">'lstrip'</span>, <span class="string">'maketrans'</span>, <span class="string">'partition'</span>, <span class="string">'replace'</span>, <span class="string">'rfind'</span>, <span class="string">'rindex'</span>, <span class="string">'rjust'</span>, <span class="string">'rpartition'</span>, <span class="string">'rsplit'</span>, <span class="string">'rstrip'</span>, <span class="string">'split'</span>, <span class="string">'splitlines'</span>, <span class="string">'startswith'</span>, <span class="string">'strip'</span>, <span class="string">'swapcase'</span>, <span class="string">'title'</span>, <span class="string">'translate'</span>, <span class="string">'upper'</span>, <span class="string">'zfill'</span>]</span><br></pre></td></tr></table></figure><a id="more"></a><h3 id="help"><a href="#help" class="headerlink" title="help()"></a>help()</h3><ul><li>作用 : 查看一个类的所有详细方法,或者查看某个方法的使用详细信息</li><li>使用方法:help([object])</li></ul><p>实例说明:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>help(list) <span class="comment"># 这样可以展示一个类下面的所有详细方法</span></span><br><span class="line">Help on <span class="class"><span class="keyword">class</span> <span class="title">list</span> <span class="title">in</span> <span class="title">module</span> <span class="title">builtins</span></span></span><br><span class="line"><span class="class"><span class="title">class</span> <span class="title">list</span><span class="params">(object)</span></span></span><br><span class="line"><span class="class"> | <span class="title">list</span><span class="params">()</span> -> new empty list</span></span><br><span class="line"><span class="class"> | list(iterable) -> new list initialized from iterable's items</span></span><br><span class="line"><span class="class"> |</span></span><br><span class="line"><span class="class"> | Methods defined here:</span></span><br><span class="line"> |</span><br><span class="line"> | __add__(self, value, /)</span><br><span class="line"> | Return self+value.</span><br><span class="line"> |</span><br><span class="line"> | __contains__(self, key, /)</span><br><span class="line"> | Return key <span class="keyword">in</span> self.</span><br><span class="line"> |</span><br><span class="line"> | __delitem__(self, key, /)</span><br><span class="line"> | Delete self[key].</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>help(list.append) <span class="comment"># 这样查看某个具体方法的详细使用信息</span></span><br><span class="line">Help on method_descriptor:</span><br><span class="line">append(...)</span><br><span class="line"> L.append(object) -> None -- append object to end</span><br></pre></td></tr></table></figure><h3 id="abs"><a href="#abs" class="headerlink" title="abs()"></a>abs()</h3><ul><li>作用:返回数字的绝对值,参数可以是整数或浮点数</li><li>使用方法:abs(num)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 相当于数学中的求绝对值</span></span><br><span class="line"><span class="meta">>>> </span>abs(<span class="number">11</span>)</span><br><span class="line"><span class="number">11</span></span><br><span class="line"><span class="meta">>>> </span>abs(<span class="number">-11</span>)</span><br><span class="line"><span class="number">11</span></span><br></pre></td></tr></table></figure><h3 id="all"><a href="#all" class="headerlink" title="all()"></a>all()</h3><ul><li>作用:all()会循环括号内的每一个元素,如果括号内的所有元素都是真的,或者如果iterable为空,则返回<code>True</code> ,如果有一个为假的那么就返回 <code>False</code></li><li>使用方法:all(iterable)</li><li>返回值:True 或者False</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看iterable中的元素是否为假可以使用bool进行查看</span></span><br><span class="line"><span class="meta">>>> </span>all([]) <span class="comment"># 当iterable为空,也返回True</span></span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>all([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]) <span class="comment"># 当iterable中所有元素都为True,则返回True</span></span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>all([<span class="number">1</span>,<span class="number">2</span>,<span class="string">''</span>]) <span class="comment"># 当iterable中元素有一个为False时,则返回False</span></span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h3 id="any"><a href="#any" class="headerlink" title="any()"></a>any()</h3><ul><li>作用:循环元素,如果有一个元素为真,那么就返回<code>True</code>,否则就返回<code>False</code></li><li>使用方法:any(iterable)</li><li>返回值:True 或者False</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>any([]) <span class="comment"># 当iterable为空,也返回False</span></span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>any([<span class="number">0</span>,<span class="string">''</span>,<span class="number">1</span>]) <span class="comment"># 当iterable中的元素存在一个为True时,则返回True</span></span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>all([<span class="number">0</span>,<span class="string">''</span>]) <span class="comment"># 当iterable中的元素为False时,则返回False</span></span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h3 id="bin"><a href="#bin" class="headerlink" title="bin()"></a>bin()</h3><ul><li>作用:将整数x转换为二进制字符串</li><li>使用方法:bin(x)</li><li>返回值: 返回一个整数的二进制字符串</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>bin(<span class="number">10</span>) <span class="comment"># 返回一个整数的二进制</span></span><br><span class="line"><span class="string">'0b1010'</span></span><br></pre></td></tr></table></figure><h3 id="bool"><a href="#bool" class="headerlink" title="bool()"></a>bool()</h3><ul><li>作用:查看一个元素的布尔值,非真即假</li><li>使用方法:bool(x)</li><li>返回值:True或False</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 假的参数有: False、0、None、""、[]、()、{}等</span></span><br><span class="line"><span class="meta">>>> </span>bool(<span class="keyword">False</span>)</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>bool(<span class="number">0</span>)</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>bool(<span class="keyword">None</span>)</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>bool([])</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>bool({})</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>bool(())</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>bool(<span class="string">'22h'</span>)</span><br><span class="line"><span class="keyword">True</span></span><br></pre></td></tr></table></figure><h3 id="callable"><a href="#callable" class="headerlink" title="callable()"></a>callable()</h3><ul><li>作用:返回一个对象是否可以被执行</li><li>使用方法:callable(object)</li><li>返回值:True或False</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">()</span>:</span> <span class="comment"># 这里定义一个函数</span></span><br><span class="line"><span class="keyword">return</span> <span class="number">123</span></span><br><span class="line">>>></span><br><span class="line"><span class="meta">>>> </span>callable(func) <span class="comment"># 判断对象是否可执行</span></span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>callable(func()) <span class="comment"># func()实际上对应的是一个123, int object不可被执行</span></span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h3 id="compile"><a href="#compile" class="headerlink" title="compile()"></a>compile()</h3><ul><li>作用:把字符串编译成python的exec或eval执行的代码</li><li>使用方法:compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>str = <span class="string">"for i in range(0,10): print(i)"</span></span><br><span class="line"><span class="meta">>>> </span>code = compile(str,<span class="string">''</span>,<span class="string">'exec'</span>)</span><br><span class="line"><span class="meta">>>> </span>exec(code)</span><br><span class="line"><span class="number">0</span></span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="number">6</span></span><br><span class="line"><span class="number">7</span></span><br><span class="line"><span class="number">8</span></span><br><span class="line"><span class="number">9</span></span><br><span class="line"><span class="meta">>>> </span>eval(code)</span><br><span class="line"><span class="number">0</span></span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="number">6</span></span><br><span class="line"><span class="number">7</span></span><br><span class="line"><span class="number">8</span></span><br><span class="line"><span class="number">9</span></span><br></pre></td></tr></table></figure><h3 id="dict"><a href="#dict" class="headerlink" title="dict()"></a>dict()</h3><ul><li>作用:创建一个数据类型为字典</li><li>语法:dict(**kwargs) dict(mapping) dict(iterable)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dict(a=<span class="number">1</span>,b=<span class="number">2</span>) <span class="comment"># **kwargs</span></span><br><span class="line">{<span class="string">'b'</span>: <span class="number">2</span>, <span class="string">'a'</span>: <span class="number">1</span>}</span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>dict(((<span class="string">'key1'</span>,<span class="number">1</span>),(<span class="string">'key2'</span>,<span class="number">2</span>),(<span class="string">'key3'</span>,<span class="number">3</span>))) <span class="comment"># mapping</span></span><br><span class="line">{<span class="string">'key2'</span>: <span class="number">2</span>, <span class="string">'key3'</span>: <span class="number">3</span>, <span class="string">'key1'</span>: <span class="number">1</span>}</span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>dict(zip([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>],[[<span class="number">12</span>,<span class="number">3</span>],<span class="number">1</span>,<span class="number">2</span>])) <span class="comment"># iterable</span></span><br><span class="line">{<span class="number">1</span>: [<span class="number">12</span>, <span class="number">3</span>], <span class="number">2</span>: <span class="number">1</span>, <span class="number">3</span>: <span class="number">2</span>}</span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>dict(enumerate([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])) <span class="comment"># iterable</span></span><br><span class="line">{<span class="number">0</span>: <span class="number">1</span>, <span class="number">1</span>: <span class="number">2</span>, <span class="number">2</span>: <span class="number">3</span>}</span><br></pre></td></tr></table></figure><h3 id="enumerate"><a href="#enumerate" class="headerlink" title="enumerate()"></a>enumerate()</h3><ul><li>作用:为元素生成下标</li><li>语法:enumerate(iterable[,start])</li><li>返回值:enumerate object</li></ul><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>enum = enumerate([<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>],<span class="number">1</span>) <span class="comment"># 指定索引从1开始</span></span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> k,v <span class="keyword">in</span> enum:</span><br><span class="line">print(k,v)</span><br><span class="line"><span class="number">1</span> a</span><br><span class="line"><span class="number">2</span> b</span><br><span class="line"><span class="number">3</span> c</span><br></pre></td></tr></table></figure><h3 id="eval"><a href="#eval" class="headerlink" title="eval()"></a>eval()</h3><ul><li>作用:把一个字符串当作一个表达式去执行</li><li>语法:eval(expression, globals=None, locals=None)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string = <span class="string">"1 + 3"</span></span><br><span class="line"><span class="meta">>>> </span>eval(string)</span><br><span class="line"><span class="number">4</span></span><br></pre></td></tr></table></figure><h3 id="exec"><a href="#exec" class="headerlink" title="exec()"></a>exec()</h3><ul><li>作用:把字符串当作python代码执行</li><li>语法:exec(object[, globals[, locals]])</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>exec(<span class="string">"for n in range(5): print(n)"</span>)</span><br><span class="line"><span class="number">0</span></span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">4</span></span><br></pre></td></tr></table></figure><h3 id="filter"><a href="#filter" class="headerlink" title="filter()"></a>filter()</h3><ul><li>作用:筛选过滤,循环可迭代的对象,把迭代的对象当作函数的参数</li><li>语法:filter(function, iterable)</li><li>返回值:fliter对象</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">(x)</span>:</span></span><br><span class="line"><span class="keyword">if</span> x == <span class="number">11</span> <span class="keyword">or</span> x == <span class="number">22</span>:</span><br><span class="line"><span class="keyword">return</span> <span class="keyword">True</span></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>ret = filter(func,[<span class="number">11</span>,<span class="number">22</span>,<span class="number">33</span>,<span class="number">44</span>])</span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> n <span class="keyword">in</span> ret:</span><br><span class="line">print(n)</span><br><span class="line"></span><br><span class="line"><span class="number">11</span></span><br><span class="line"><span class="number">22</span></span><br></pre></td></tr></table></figure><h3 id="globals"><a href="#globals" class="headerlink" title="globals()"></a>globals()</h3><ul><li>作用:获取或修改当前文件内的全局变量</li><li>语法:globals()</li></ul><p>实例说明:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>globals()</span><br><span class="line">{'string': '1 + 3', 'func': <function func at 0x0000000003782048>, 'k': 3, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'code': <code object <module> at 0x0000000003733DB0, file "", line 1>, '__doc__': None, '__package__': None, 'ret': <filter object at 0x000000000378DE80>, '__builtins__': <module 'builtins' (built-in)>, 'v': 'c', '__name__': '__main__', 'str': '1 + 1 = 2', 'enum': <enumerate object at 0x0000000003780C18>, 'i': 9, '__spec__': None, 'n': 22}</span><br></pre></td></tr></table></figure><h3 id="hash"><a href="#hash" class="headerlink" title="hash()"></a>hash()</h3><ul><li>作用:返回一个对象的hash值</li><li>语法:hash(object)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>a = <span class="string">'wuwfhrfyfh'</span></span><br><span class="line"><span class="meta">>>> </span>hash(a)</span><br><span class="line"><span class="number">2464845681420772089</span></span><br></pre></td></tr></table></figure><h3 id="hex"><a href="#hex" class="headerlink" title="hex()"></a>hex()</h3><ul><li>作用:获取一个数的十六进制</li><li>语法:hex(x)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>hex(<span class="number">888</span>)</span><br><span class="line"><span class="string">'0x378'</span></span><br></pre></td></tr></table></figure><h3 id="id"><a href="#id" class="headerlink" title="id()"></a>id()</h3><ul><li>作用:返回一个对象的内存地址</li><li>语法:id(object)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>a = <span class="number">123</span></span><br><span class="line"><span class="meta">>>> </span>id(a)</span><br><span class="line"><span class="number">499388688</span></span><br></pre></td></tr></table></figure><h3 id="input"><a href="#input" class="headerlink" title="input()"></a>input()</h3><ul><li>作用:交互式输入</li><li>语法:input([prompt])</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>num = input(<span class="string">"please input your num: "</span>)</span><br><span class="line">please input your num: <span class="number">10</span></span><br><span class="line"><span class="meta">>>> </span>type(num) <span class="comment"># 注意类型为str型</span></span><br><span class="line"><<span class="class"><span class="keyword">class</span> '<span class="title">str</span>'></span></span><br></pre></td></tr></table></figure><h3 id="int"><a href="#int" class="headerlink" title="int()"></a>int()</h3><ul><li>作用:转换字符串或数字为int型</li><li>语法:int(x, base=10)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>int(<span class="string">"31"</span>)</span><br><span class="line"><span class="number">31</span></span><br><span class="line"><span class="comment"># 进制转换</span></span><br><span class="line"><span class="meta">>>> </span>int(<span class="string">'0b11'</span>,base=<span class="number">2</span>)</span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="meta">>>> </span>int(<span class="string">'11'</span>,base=<span class="number">8</span>)</span><br><span class="line"><span class="number">9</span></span><br><span class="line"><span class="meta">>>> </span>int(<span class="string">'0xe'</span>,base=<span class="number">16</span>)</span><br><span class="line"><span class="number">14</span></span><br></pre></td></tr></table></figure><h3 id="isinstance"><a href="#isinstance" class="headerlink" title="isinstance()"></a>isinstance()</h3><ul><li>作用:判断对象是否是这个类创建的</li><li>语法:isinstance(object, classinfo)</li><li>返回值: True或者False</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>the_list = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]</span><br><span class="line"><span class="meta">>>> </span>isinstance(the_list,list)</span><br><span class="line"><span class="keyword">True</span></span><br></pre></td></tr></table></figure><h3 id="iter"><a href="#iter" class="headerlink" title="iter()"></a>iter()</h3><ul><li>作用:创建一个迭代器</li><li>语法:iter(iterable) iter(callable, sentinel)</li><li>返回值:iterator 迭代器</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>obj = iter([<span class="number">11</span>,<span class="number">22</span>,<span class="number">33</span>,<span class="number">44</span>])</span><br><span class="line"><span class="meta">>>> </span>type(obj)</span><br><span class="line"><<span class="class"><span class="keyword">class</span> '<span class="title">list_iterator</span>'></span></span><br><span class="line"><span class="class">>>> <span class="title">for</span> <span class="title">n</span> <span class="title">in</span> <span class="title">obj</span>:</span></span><br><span class="line">print(n)</span><br><span class="line"><span class="number">11</span></span><br><span class="line"><span class="number">22</span></span><br><span class="line"><span class="number">33</span></span><br><span class="line"><span class="number">44</span></span><br></pre></td></tr></table></figure><h3 id="len"><a href="#len" class="headerlink" title="len()"></a>len()</h3><ul><li>作用:返回一个容器中包含item的数量</li><li>语法:len(object)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>url = <span class="string">"chenfanlinux"</span></span><br><span class="line"><span class="meta">>>> </span>len(url)</span><br><span class="line"><span class="number">12</span></span><br></pre></td></tr></table></figure><h3 id="list"><a href="#list" class="headerlink" title="list()"></a>list()</h3><ul><li>作用:生成一个list对象</li><li>语法:list(iterable)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>li = list([<span class="number">11</span>,<span class="number">22</span>,<span class="number">33</span>,<span class="number">44</span>])</span><br><span class="line"><span class="meta">>>> </span>li</span><br><span class="line">[<span class="number">11</span>, <span class="number">22</span>, <span class="number">33</span>, <span class="number">44</span>]</span><br></pre></td></tr></table></figure><h3 id="locals"><a href="#locals" class="headerlink" title="locals()"></a>locals()</h3><ul><li>作用:返回当前作用域的局部变量</li><li>语法:locals()</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">()</span>:</span></span><br><span class="line">name = <span class="string">'chenfanlinux'</span></span><br><span class="line">print(locals())</span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>func()</span><br><span class="line">{<span class="string">'name'</span>: <span class="string">'chenfanlinux'</span>}</span><br></pre></td></tr></table></figure><h3 id="map"><a href="#map" class="headerlink" title="map()"></a>map()</h3><ul><li>作用:对一个序列中的每一个元素都传到函数中执行并返回</li><li>语法:map(func, *iterables)</li><li>返回值:map object</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list(map((<span class="keyword">lambda</span> x : x +<span class="number">10</span>),[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]))</span><br><span class="line">[<span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>, <span class="number">14</span>]</span><br></pre></td></tr></table></figure><h3 id="next"><a href="#next" class="headerlink" title="next()"></a>next()</h3><ul><li>作用:返回迭代器下一个item</li><li>语法:next(iterator[, default])</li><li>返回值:迭代器中当前迭代的元素</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>obj = iter([<span class="number">11</span>,<span class="number">22</span>,<span class="number">33</span>,<span class="number">44</span>]) <span class="comment"># 生成迭代器</span></span><br><span class="line"><span class="meta">>>> </span>next(obj)</span><br><span class="line"><span class="number">11</span></span><br><span class="line"><span class="meta">>>> </span>next(obj)</span><br><span class="line"><span class="number">22</span></span><br><span class="line"><span class="meta">>>> </span>next(obj)</span><br><span class="line"><span class="number">33</span></span><br><span class="line"><span class="meta">>>> </span>next(obj)</span><br><span class="line"><span class="number">44</span></span><br><span class="line"><span class="meta">>>> </span>next(obj) <span class="comment"># 迭代完没有可迭代元素后会报错</span></span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<pyshell#241>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line"> next(obj)</span><br><span class="line">StopIteration</span><br></pre></td></tr></table></figure><h3 id="ord"><a href="#ord" class="headerlink" title="ord()"></a>ord()</h3><ul><li>作用:把一个字母转换为ASCII对对应表中的数字</li><li>语法:ord(c)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>ord(<span class="string">"a"</span>)</span><br><span class="line"><span class="number">97</span></span><br></pre></td></tr></table></figure><h3 id="pow"><a href="#pow" class="headerlink" title="pow()"></a>pow()</h3><ul><li>作用:返回一个数的N次方</li><li>语法:pow(x, y[, z])</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> >>> pow(<span class="number">2</span>, <span class="number">10</span>)</span><br><span class="line"><span class="number">1024</span></span><br><span class="line"> >>> pow(<span class="number">2</span>, <span class="number">20</span>)</span><br><span class="line"><span class="number">1048576</span></span><br></pre></td></tr></table></figure><h3 id="print"><a href="#print" class="headerlink" title="print()"></a>print()</h3><ul><li>作用:打印输出</li><li>语法:print(value, …, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>print(<span class="string">'hello world'</span>,end=<span class="string">'@@@'</span>);print(<span class="string">"com"</span>)</span><br><span class="line">hello world@@@com</span><br></pre></td></tr></table></figure><h3 id="range"><a href="#range" class="headerlink" title="range()"></a>range()</h3><ul><li>作用:生成一个序列</li><li>语法:range(start, stop[, step])</li><li>返回值:range object</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> n <span class="keyword">in</span> range(<span class="number">0</span>,<span class="number">10</span>,<span class="number">2</span>):</span><br><span class="line">print(n)</span><br><span class="line"><span class="number">0</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="number">6</span></span><br><span class="line"><span class="number">8</span></span><br></pre></td></tr></table></figure><h3 id="repr"><a href="#repr" class="headerlink" title="repr()"></a>repr()</h3><ul><li>作用:返回一个包含对象的可打印表示的字符串</li><li>语法:repr(object)</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>repr(<span class="number">111</span>)</span><br><span class="line"><span class="string">'111'</span></span><br><span class="line"><span class="meta">>>> </span>repr(<span class="number">111.11</span>)</span><br><span class="line"><span class="string">'111.11'</span></span><br></pre></td></tr></table></figure><h3 id="reversed"><a href="#reversed" class="headerlink" title="reversed()"></a>reversed()</h3><ul><li>作用:对一个对象的元素进行反转</li><li>语法:reversed(sequence)</li><li>返回值:reverse iterator</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>li = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]</span><br><span class="line"><span class="meta">>>> </span>reversed(li)</span><br><span class="line"><list_reverseiterator object at <span class="number">0x00000000034F5B38</span>></span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> n <span class="keyword">in</span> reversed(li):</span><br><span class="line">print(n)</span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">1</span></span><br></pre></td></tr></table></figure><h3 id="round"><a href="#round" class="headerlink" title="round()"></a>round()</h3><ul><li>作用:四舍五入</li><li>语法:round(number[, ndigits])</li></ul><p>实例说明:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>round(<span class="number">2.788</span>,<span class="number">2</span>)</span><br><span class="line"><span class="number">2.79</span></span><br></pre></td></tr></table></figure><h3 id="sorted"><a href="#sorted" class="headerlink" title="sorted()"></a>sorted()</h3><ul><li>作用:为一个对象的元素进行排序</li><li>语法:sorted(iterable, key=None, reverse=False)</li><li>返回值:一个排序好的对象</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>char = [<span class="string">'1hfhf'</span>,<span class="string">'yye'</span>,<span class="string">'fhfhfhhfh'</span>,<span class="string">'e'</span>,<span class="string">'fhfhhf2'</span>]</span><br><span class="line"><span class="meta">>>> </span>char</span><br><span class="line">[<span class="string">'1hfhf'</span>, <span class="string">'yye'</span>, <span class="string">'fhfhfhhfh'</span>, <span class="string">'e'</span>, <span class="string">'fhfhhf2'</span>]</span><br><span class="line"><span class="meta">>>> </span>sorted(char,key=<span class="keyword">lambda</span> x:len(x)) <span class="comment"># key后面跟函数,根据函数的返回值进行排序,默认为升序</span></span><br><span class="line">[<span class="string">'e'</span>, <span class="string">'yye'</span>, <span class="string">'1hfhf'</span>, <span class="string">'fhfhhf2'</span>, <span class="string">'fhfhfhhfh'</span>]</span><br><span class="line"><span class="meta">>>> </span>char <span class="comment"># 排序后,原对象不会修改</span></span><br><span class="line">[<span class="string">'1hfhf'</span>, <span class="string">'yye'</span>, <span class="string">'fhfhfhhfh'</span>, <span class="string">'e'</span>, <span class="string">'fhfhhf2'</span>]</span><br></pre></td></tr></table></figure><h3 id="type"><a href="#type" class="headerlink" title="type()"></a>type()</h3><ul><li>作用:返回对象的数据类型</li><li>语法:type(object)</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"> >>> a = <span class="number">1</span></span><br><span class="line"> >>> type(a)</span><br><span class="line"><<span class="class"><span class="keyword">class</span> '<span class="title">int</span>'></span></span><br><span class="line"> >>> a = "str"</span><br><span class="line"> >>> type(a)</span><br><span class="line"><<span class="class"><span class="keyword">class</span> '<span class="title">str</span>'></span></span><br></pre></td></tr></table></figure><h3 id="zip"><a href="#zip" class="headerlink" title="zip()"></a>zip()</h3><ul><li>作用:生成一个一对一的zip对象</li><li>语法:zip(iter1 [,iter2 […]])</li><li>返回值:zip object</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>li1 = [<span class="string">"k1"</span>,<span class="string">"k2"</span>,<span class="string">"k3"</span>]</span><br><span class="line"><span class="meta">>>> </span>li2 = [<span class="string">"a"</span>,<span class="string">"b"</span>,<span class="string">"c"</span>]</span><br><span class="line"><span class="meta">>>> </span>d = zip(li1,li2)</span><br><span class="line"><span class="meta">>>> </span>the_dict = dict(zip(li1,li2)) <span class="comment"># 转换成字典</span></span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> k,v <span class="keyword">in</span> d:</span><br><span class="line">print(k,v)</span><br><span class="line">k1 a</span><br><span class="line">k2 b</span><br><span class="line">k3 c</span><br></pre></td></tr></table></figure><h2 id="字符串内建函数"><a href="#字符串内建函数" class="headerlink" title="字符串内建函数"></a>字符串内建函数</h2><p>正是因为 python 内置提供的方法足够多,才使得在开发时,能够针对字符串进行更加灵活的操作!应对更多的开发需求!可以通过下面的方式查看这种数据类型生产出来的对象所对应的方法。</p><ul><li><p>在 <code>ipython3</code> 中定义一个 <strong>字符串</strong>,例如:<code>hello_str = ""</code> , 输入 <code>hello_str.</code> 按下 <code>TAB</code> 键,<code>ipython</code> 会提示 <strong>字符串</strong> 能够使用的 <strong>方法</strong> 如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">In [<span class="number">1</span>]: hello_str.</span><br><span class="line">hello_str.capitalize hello_str.isidentifier hello_str.rindex</span><br><span class="line">hello_str.casefold hello_str.islower hello_str.rjust</span><br><span class="line">hello_str.center hello_str.isnumeric hello_str.rpartition</span><br><span class="line">hello_str.count hello_str.isprintable hello_str.rsplit</span><br><span class="line">hello_str.encode hello_str.isspace hello_str.rstrip</span><br><span class="line">hello_str.endswith hello_str.istitle hello_str.split</span><br><span class="line">hello_str.expandtabs hello_str.isupper hello_str.splitlines</span><br><span class="line">hello_str.find hello_str.join hello_str.startswith</span><br><span class="line">hello_str.format hello_str.ljust hello_str.strip</span><br><span class="line">hello_str.format_map hello_str.lower hello_str.swapcase</span><br><span class="line">hello_str.index hello_str.lstrip hello_str.title</span><br><span class="line">hello_str.isalnum hello_str.maketrans hello_str.translate</span><br><span class="line">hello_str.isalpha hello_str.partition hello_str.upper</span><br><span class="line">hello_str.isdecimal hello_str.replace hello_str.zfill</span><br><span class="line">hello_str.isdigit hello_str.rfind</span><br></pre></td></tr></table></figure></li><li><p>通过dir()函数,可以查看到对象的方法及其属性。</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dir(str)</span><br><span class="line">[<span class="string">'__add__'</span>, <span class="string">'__class__'</span>, <span class="string">'__contains__'</span>, <span class="string">'__delattr__'</span>, <span class="string">'__dir__'</span>, <span class="string">'__doc__'</span>, <span class="string">'__eq__'</span>, <span class="string">'__format__'</span>, <span class="string">'__ge__'</span>, <span class="string">'__getattribute__'</span>, <span class="string">'__getitem__'</span>, <span class="string">'__getnewargs__'</span>, <span class="string">'__gt__'</span>, <span class="string">'__hash__'</span>, <span class="string">'__init__'</span>, <span class="string">'__iter__'</span>, <span class="string">'__le__'</span>, <span class="string">'__len__'</span>, <span class="string">'__lt__'</span>, <span class="string">'__mod__'</span>, <span class="string">'__mul__'</span>, <span class="string">'__ne__'</span>, <span class="string">'__new__'</span>, <span class="string">'__reduce__'</span>, <span class="string">'__reduce_ex__'</span>, <span class="string">'__repr__'</span>, <span class="string">'__rmod__'</span>, <span class="string">'__rmul__'</span>, <span class="string">'__setattr__'</span>, <span class="string">'__sizeof__'</span>, <span class="string">'__str__'</span>, <span class="string">'__subclasshook__'</span>, <span class="string">'capitalize'</span>, <span class="string">'casefold'</span>, <span class="string">'center'</span>, <span class="string">'count'</span>, <span class="string">'encode'</span>, <span class="string">'endswith'</span>, <span class="string">'expandtabs'</span>, <span class="string">'find'</span>, <span class="string">'format'</span>, <span class="string">'format_map'</span>, <span class="string">'index'</span>, <span class="string">'isalnum'</span>, <span class="string">'isalpha'</span>, <span class="string">'isdecimal'</span>, <span class="string">'isdigit'</span>, <span class="string">'isidentifier'</span>, <span class="string">'islower'</span>, <span class="string">'isnumeric'</span>, <span class="string">'isprintable'</span>, <span class="string">'isspace'</span>, <span class="string">'istitle'</span>, <span class="string">'isupper'</span>, <span class="string">'join'</span>, <span class="string">'ljust'</span>, <span class="string">'lower'</span>, <span class="string">'lstrip'</span>, <span class="string">'maketrans'</span>, <span class="string">'partition'</span>, <span class="string">'replace'</span>, <span class="string">'rfind'</span>, <span class="string">'rindex'</span>, <span class="string">'rjust'</span>, <span class="string">'rpartition'</span>, <span class="string">'rsplit'</span>, <span class="string">'rstrip'</span>, <span class="string">'split'</span>, <span class="string">'splitlines'</span>, <span class="string">'startswith'</span>, <span class="string">'strip'</span>, <span class="string">'swapcase'</span>, <span class="string">'title'</span>, <span class="string">'translate'</span>, <span class="string">'upper'</span>, <span class="string">'zfill'</span>]</span><br></pre></td></tr></table></figure><h3 id="判断类型"><a href="#判断类型" class="headerlink" title="判断类型"></a>判断类型</h3><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>string.isspace()</td><td>如果 string 中只包含空格,则返回 True</td></tr><tr><td>string.isalnum()</td><td>如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True</td></tr><tr><td>string.isalpha()</td><td>如果 string 至少有一个字符并且所有字符都是字母则返回 True</td></tr><tr><td>string.isdecimal()</td><td>如果 string 只包含数字则返回 True,<code>全角数字</code></td></tr><tr><td>string.isdigit()</td><td>如果 string 只包含数字则返回 True,<code>全角数字</code>、<code>⑴</code>、<code>\u00b2</code></td></tr><tr><td>string.isnumeric()</td><td>如果 string 只包含数字则返回 True,<code>全角数字</code>,<code>汉字数字</code></td></tr><tr><td>string.istitle()</td><td>如果 string 是标题化的(每个单词的首字母大写)则返回 True</td></tr><tr><td>string.islower()</td><td>如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True</td></tr><tr><td>string.isupper()</td><td>如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True</td></tr></tbody></table><h4 id="isspace"><a href="#isspace" class="headerlink" title="isspace()"></a>isspace()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 如果变量内容由空格来组成,那么就返回`True`否则就返回`False`</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">" "</span></span><br><span class="line"><span class="meta">>>> </span>string.isspace()</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"a"</span></span><br><span class="line"><span class="meta">>>> </span>string.isspace()</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h4 id="isalnum"><a href="#isalnum" class="headerlink" title="isalnum()"></a>isalnum()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hes2323"</span></span><br><span class="line"><span class="comment"># 如果存在数字或字母就返回`True`,否则返回`False`</span></span><br><span class="line"><span class="meta">>>> </span>string.isalnum()</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="comment"># 中间有空格返回的就是False了</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string.isalnum()</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h4 id="isalpha"><a href="#isalpha" class="headerlink" title="isalpha()"></a>isalpha()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 如果全部都是字母就返回`True`</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"helloword"</span></span><br><span class="line"><span class="meta">>>> </span>string.isalpha()</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="comment"># 否则就返回False</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"hes2323"</span></span><br><span class="line"><span class="meta">>>> </span>string.isalpha()</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h4 id="isdecimal-、isdigit-、isnumeric"><a href="#isdecimal-、isdigit-、isnumeric" class="headerlink" title="isdecimal() 、isdigit() 、isnumeric()"></a>isdecimal() 、isdigit() 、isnumeric()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1.只能判断整数,小数全为Fasle</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">'1.1'</span>.isdecimal()</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">'1.1'</span>.isdigit()</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">'1.1'</span>.isnumeric()</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. isdecimal(全角数字) 、isdigit(全角数字, ⑴, \u00b2) 、isnumeric(全角数字, 汉字数字)</span></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span><span class="string">'⑴'</span>.isdecimal()</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">'⑴'</span>.isdigit()</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">'⑴'</span>.isnumeric()</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 汉字数字</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">"一千零一"</span>.isdecimal()</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">"一千零一"</span>.isdigit()</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">"一千零一"</span>.isnumeric()</span><br><span class="line"><span class="keyword">True</span></span><br></pre></td></tr></table></figure><h4 id="istitle"><a href="#istitle" class="headerlink" title="istitle()"></a>istitle()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 如果变量的内容首字母是大写并且其他字母为小写,那么就返回`True`,否则会返回`False`</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"Hello Word"</span></span><br><span class="line"><span class="meta">>>> </span>string.istitle()</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"Hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string.istitle()</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h4 id="islower"><a href="#islower" class="headerlink" title="islower()"></a>islower()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 如果变量内容全部都是小写字母就返回`True`,否则就返回`False`</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"hesasdasd"</span></span><br><span class="line"><span class="meta">>>> </span>string.islower()</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"HelloWord"</span></span><br><span class="line"><span class="meta">>>> </span>string.islower()</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h4 id="isupper"><a href="#isupper" class="headerlink" title="isupper()"></a>isupper()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 如果变量值中所有的字母都是大写就返回`True`,否则就返回`False`</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string.isupper()</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"HELLO WORD"</span></span><br><span class="line"><span class="meta">>>> </span>string.isupper()</span><br><span class="line"><span class="keyword">True</span></span><br></pre></td></tr></table></figure><h3 id="查找和替换"><a href="#查找和替换" class="headerlink" title="查找和替换"></a>查找和替换</h3><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>string.startswith(str)</td><td>检查字符串是否是以 str 开头,是则返回 True</td></tr><tr><td>string.endswith(str)</td><td>检查字符串是否是以 str 结束,是则返回 True</td></tr><tr><td>string.find(str, start=0, end=len(string))</td><td>检测 str 是否包含在 string 中,如果 start 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回 <code>-1</code></td></tr><tr><td>string.rfind(str, start=0, end=len(string))</td><td>类似于 find(),不过是从右边开始查找</td></tr><tr><td>string.index(str, start=0, end=len(string))</td><td>跟 find() 方法类似,不过如果 str 不在 string 会报错</td></tr><tr><td>string.rindex(str, start=0, end=len(string))</td><td>类似于 index(),不过是从右边开始</td></tr><tr><td>string.replace(old_str, new_str, num=string.count(old))</td><td>把 string 中的 old_str 替换成 new_str,如果 num 指定,则替换不超过 num 次</td></tr></tbody></table><h4 id="startswith"><a href="#startswith" class="headerlink" title="startswith()"></a>startswith()</h4><p>检查字符串是否是以指定子字符串开头,如果是则返回 True,否则返回 False。如果参数 start 和 end 指定值,则在指定范围内检查。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"www.chenfanlinux.org"</span></span><br><span class="line"><span class="meta">>>> </span>string.startswith(<span class="string">"www"</span>)</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>string.startswith(<span class="string">"www"</span>,<span class="number">3</span>)</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><h4 id="endswith"><a href="#endswith" class="headerlink" title="endswith"></a>endswith</h4><p>判断字符串是否以指定后缀结尾,如果以指定后缀结尾返回True,否则返回False。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="comment"># 判断字符串中是否已"d"结尾,如果是则返回"True"</span></span><br><span class="line"><span class="meta">>>> </span>string.endswith(<span class="string">"d"</span>)</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="comment"># 判断字符串中是否已"t"结尾,不是则返回"False"</span></span><br><span class="line"><span class="meta">>>> </span>string.endswith(<span class="string">"t"</span>)</span><br><span class="line"><span class="keyword">False</span></span><br><span class="line"><span class="comment"># 制定搜索的位置,实则就是从字符串位置1到7来进行判断,如果第七个位置是"d",则返回True,否则返回False</span></span><br><span class="line"><span class="meta">>>> </span>string.endswith(<span class="string">"d"</span>,<span class="number">1</span>,<span class="number">7</span>)</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure><p>####</p><h4 id="find"><a href="#find" class="headerlink" title="find()"></a>find()</h4><p>检测字符串中是否包含子字符串str,如果指定start(开始)和end(结束)范围,则检查是否包含在指定范围内,如果包含子字符串返回开始的索引值,否则返回-1。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="comment"># 返回`o`在当前字符串中的位置,如果找到第一个`o`之后就不会再继续往下面寻找了</span></span><br><span class="line"><span class="meta">>>> </span>string.find(<span class="string">"o"</span>)</span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="comment"># 从第五个位置开始搜索,返回`o`所在的位置</span></span><br><span class="line"><span class="meta">>>> </span>string.find(<span class="string">"o"</span>,<span class="number">5</span>)</span><br><span class="line"><span class="number">7</span></span><br></pre></td></tr></table></figure><h4 id="rfind"><a href="#rfind" class="headerlink" title="rfind()"></a>rfind()</h4><p>返回字符串最后一次出现的位置,如果没有匹配项则返回-1</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="comment"># rfind其实就是反向查找</span></span><br><span class="line"><span class="meta">>>> </span>string.rfind(<span class="string">"o"</span>)</span><br><span class="line"><span class="number">7</span></span><br><span class="line"><span class="comment"># 指定查找的范围</span></span><br><span class="line"><span class="meta">>>> </span>string.rfind(<span class="string">"o"</span>,<span class="number">0</span>,<span class="number">6</span>)</span><br><span class="line"><span class="number">4</span></span><br></pre></td></tr></table></figure><h4 id="index"><a href="#index" class="headerlink" title="index()"></a>index()</h4><p>检测字符串中是否包含子字符串 str ,如果指定 start(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,该方法与 python find()方法一样,只不过如果str不在 string中会报一个异常。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="comment"># 返回字符串所在的位置</span></span><br><span class="line"><span class="meta">>>> </span>string.index(<span class="string">"o"</span>)</span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="comment"># 如果查找一个不存在的字符串那么就会报错</span></span><br><span class="line"><span class="meta">>>> </span>string.index(<span class="string">"a"</span>)</span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">ValueError: substring <span class="keyword">not</span> found</span><br></pre></td></tr></table></figure><h4 id="rindex"><a href="#rindex" class="headerlink" title="rindex()"></a>rindex()</h4><p>返回子字符串str在字符串中最后出现的位置,如果没有匹配的字符串会报异常,你可以指定可选参数<code>[start:end]</code>设置查找的区间。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="comment"># 反向查找索引</span></span><br><span class="line"><span class="meta">>>> </span>string.rindex(<span class="string">"o"</span>)</span><br><span class="line"><span class="number">7</span></span><br><span class="line"><span class="comment"># 如果没有查找到就报错</span></span><br><span class="line"><span class="meta">>>> </span>string.rindex(<span class="string">"a"</span>)</span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">ValueError: substring <span class="keyword">not</span> found</span><br></pre></td></tr></table></figure><h4 id="replace"><a href="#replace" class="headerlink" title="replace()"></a>replace()</h4><p>把字符串中的 old(旧字符串)替换成new(新字符串),如果指定第三个参数max,则替换不超过max次</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"www.chenfanlinux.org"</span></span><br><span class="line"><span class="comment"># 把就字符串`www.`换成新字符串`https://`</span></span><br><span class="line"><span class="meta">>>> </span>string.replace(<span class="string">"www."</span>,<span class="string">"https://"</span>)</span><br><span class="line"><span class="string">'https://chenfanlinux.org'</span></span><br><span class="line"><span class="comment"># 就字符串`w`换成新字符串`a`只替换`2`次</span></span><br><span class="line"><span class="meta">>>> </span>string.replace(<span class="string">"w"</span>,<span class="string">"a"</span>,<span class="number">2</span>)</span><br><span class="line"><span class="string">'aaw.chenfanlinux.org'</span></span><br></pre></td></tr></table></figure><h3 id="大小写转换"><a href="#大小写转换" class="headerlink" title="大小写转换"></a>大小写转换</h3><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>string.capitalize()</td><td>把字符串的第一个字符大写</td></tr><tr><td>string.title()</td><td>把字符串的每个单词首字母大写</td></tr><tr><td>string.lower()</td><td>转换 string 中所有大写字符为小写</td></tr><tr><td>string.upper()</td><td>转换 string 中的小写字母为大写</td></tr><tr><td>string.swapcase()</td><td>翻转 string 中的大小写</td></tr></tbody></table><h4 id="capitalize"><a href="#capitalize" class="headerlink" title="capitalize()"></a>capitalize()</h4><p>把字符串的第一个字符大写</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name=<span class="string">"chenfanlinux"</span></span><br><span class="line"><span class="meta">>>> </span>name.capitalize()</span><br><span class="line"><span class="string">'chenfanlinux'</span></span><br></pre></td></tr></table></figure><h4 id="title"><a href="#title" class="headerlink" title="title()"></a>title()</h4><p>返回”标题化”的字符串,就是说所有单词都是以大写开始,其余字母均为小写。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string.title()</span><br><span class="line"><span class="string">'Hello Word'</span></span><br></pre></td></tr></table></figure><h4 id="lower"><a href="#lower" class="headerlink" title="lower()"></a>lower()</h4><p>转换字符串中所有大写字符为小写。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 把变量里的大写全部转换成小写</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"Hello WORD"</span></span><br><span class="line"><span class="meta">>>> </span>string.lower()</span><br><span class="line"><span class="string">'hello word'</span></span><br></pre></td></tr></table></figure><h4 id="upper"><a href="#upper" class="headerlink" title="upper()"></a>upper()</h4><p>将字符串中的小写字母转为大写字母</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string.upper()</span><br><span class="line"><span class="string">'HELLO WORD'</span></span><br></pre></td></tr></table></figure><h4 id="swapcase"><a href="#swapcase" class="headerlink" title="swapcase()"></a>swapcase()</h4><p>用于对字符串的大小写字母进行转换,大写变小写,小写变大写</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello WORD"</span></span><br><span class="line"><span class="meta">>>> </span>string.swapcase()</span><br><span class="line"><span class="string">'HELLO word'</span></span><br></pre></td></tr></table></figure><h3 id="文本对齐"><a href="#文本对齐" class="headerlink" title="文本对齐"></a>文本对齐</h3><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>string.ljust(width)</td><td>返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串</td></tr><tr><td>string.rjust(width)</td><td>返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串</td></tr><tr><td>string.center(width)</td><td>返回一个原字符串居中,并使用空格填充至长度 width 的新字符串</td></tr></tbody></table><h4 id="ljust"><a href="#ljust" class="headerlink" title="ljust()"></a>ljust()</h4><p>返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"helo word"</span></span><br><span class="line"><span class="meta">>>> </span>len(string)</span><br><span class="line"><span class="number">9</span></span><br><span class="line"><span class="comment"># 定义的长度减去字符串的长度,剩下的就开始填充</span></span><br><span class="line"><span class="meta">>>> </span>string.ljust(<span class="number">15</span>,<span class="string">'*'</span>)</span><br><span class="line"><span class="string">'helo word******'</span></span><br></pre></td></tr></table></figure><h4 id="rjust"><a href="#rjust" class="headerlink" title="rjust()"></a>rjust()</h4><p>返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串。如果指定的长度小于字符串的长度则返回原字符串。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>len(string)</span><br><span class="line"><span class="number">10</span></span><br><span class="line"><span class="meta">>>> </span>string.rjust(<span class="number">10</span>,<span class="string">"*"</span>)</span><br><span class="line"><span class="string">'hello word'</span></span><br><span class="line"><span class="meta">>>> </span>string.rjust(<span class="number">12</span>,<span class="string">"*"</span>)</span><br><span class="line"><span class="string">'**hello word'</span></span><br></pre></td></tr></table></figure><h4 id="center"><a href="#center" class="headerlink" title="center()"></a>center()</h4><p>内容居中,width:字符串的总宽度;fillchar:填充字符,默认填充字符为空格。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 定义一个字符串变量,名为"string",内容为"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="comment"># 输出这个字符串的长度,用len(value_name)</span></span><br><span class="line"><span class="meta">>>> </span>len(string)</span><br><span class="line"><span class="number">10</span></span><br><span class="line"><span class="comment"># 字符串的总宽度为10,填充的字符为"*"</span></span><br><span class="line"><span class="meta">>>> </span>string.center(<span class="number">10</span>,<span class="string">"*"</span>)</span><br><span class="line"><span class="string">'hello word'</span></span><br><span class="line"><span class="comment"># 如果设置字符串的总产都为11,那么减去字符串长度10还剩下一个位置,这个位置就会被*所占用</span></span><br><span class="line"><span class="meta">>>> </span>string.center(<span class="number">11</span>,<span class="string">"*"</span>)</span><br><span class="line"><span class="string">'*hello word'</span></span><br><span class="line"><span class="comment"># 是从左到右开始填充</span></span><br><span class="line"><span class="meta">>>> </span>string.center(<span class="number">12</span>,<span class="string">"*"</span>)</span><br><span class="line"><span class="string">'*hello word*'</span></span><br></pre></td></tr></table></figure><h3 id="去除空白字符"><a href="#去除空白字符" class="headerlink" title="去除空白字符"></a>去除空白字符</h3><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>string.lstrip()</td><td>截掉 string 左边(开始)的空白字符</td></tr><tr><td>string.rstrip()</td><td>截掉 string 右边(末尾)的空白字符</td></tr><tr><td>string.strip()</td><td>截掉 string 左右两边的空白字符</td></tr></tbody></table><h4 id="lstrip"><a href="#lstrip" class="headerlink" title="lstrip()"></a>lstrip()</h4><p>截掉字符串左边的空格或指定字符</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 从左侧开始删除匹配的字符串</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string.lstrip(<span class="string">"hello "</span>)</span><br><span class="line"><span class="string">'word'</span></span><br></pre></td></tr></table></figure><h4 id="rstrip"><a href="#rstrip" class="headerlink" title="rstrip()"></a>rstrip()</h4><p>删除string字符串末尾的指定字符(默认为空格)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 从尾部开始匹配删除</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"hello word"</span></span><br><span class="line"><span class="meta">>>> </span>string.rstrip(<span class="string">"d"</span>)</span><br><span class="line"><span class="string">'hello wor'</span></span><br></pre></td></tr></table></figure><h4 id="strip"><a href="#strip" class="headerlink" title="strip()"></a>strip()</h4><p>移除字符串头尾指定的字符(默认为空格)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">" www.chenfanlinux.org "</span></span><br><span class="line"><span class="meta">>>> </span>string</span><br><span class="line"><span class="string">' www.chenfanlinux.org '</span></span><br><span class="line"><span class="comment"># 删除空格</span></span><br><span class="line"><span class="meta">>>> </span>string.strip()</span><br><span class="line"><span class="string">'www.chenfanlinux.org'</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"_www.chenfanlinux.org_"</span></span><br><span class="line"><span class="comment"># 指定要把左右两边的"_"删除掉</span></span><br><span class="line"><span class="meta">>>> </span>string.strip(<span class="string">"_"</span>)</span><br><span class="line"><span class="string">'www.chenfanlinux.org'</span></span><br></pre></td></tr></table></figure><h3 id="拆分和连接"><a href="#拆分和连接" class="headerlink" title="拆分和连接"></a>拆分和连接</h3><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>string.partition(str)</td><td>把字符串 string 分成一个 3 元素的元组 (str前面, str, str后面)</td></tr><tr><td>string.rpartition(str)</td><td>类似于 partition() 方法,不过是从右边开始查找</td></tr><tr><td>string.split(str=””, num)</td><td>以 str 为分隔符拆分 string,如果 num 有指定值,则仅分隔 num + 1 个子字符串,str 默认包含 ‘\r’, ‘\t’, ‘\n’ 和空格</td></tr><tr><td>string.splitlines()</td><td>按照行(‘\r’, ‘\n’, ‘\r\n’)分隔,返回一个包含各行作为元素的列表</td></tr><tr><td>string.join(seq)</td><td>以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串</td></tr></tbody></table><h4 id="partition"><a href="#partition" class="headerlink" title="partition()"></a>partition()</h4><p>用来根据指定的分隔符将字符串进行分割,如果字符串包含指定的分隔符,则返回一个3元的tuple,第一个为分隔符左边的子串,第二个为分隔符本身,第三个为分隔符右边的子串。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 返回的是一个元组类型</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"www.chenfanlinux.org"</span></span><br><span class="line"><span class="meta">>>> </span>string.partition(<span class="string">"chenfanlinux"</span>)</span><br><span class="line">(<span class="string">'www.'</span>, <span class="string">'chenfanlinux'</span>, <span class="string">'.org'</span>)</span><br></pre></td></tr></table></figure><h4 id="rpartition"><a href="#rpartition" class="headerlink" title="rpartition()"></a>rpartition()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"www.chenfanlinux.org"</span></span><br><span class="line"><span class="meta">>>> </span>string.rpartition(<span class="string">"chenfanlinux"</span>)</span><br><span class="line">(<span class="string">'www.'</span>, <span class="string">'chenfanlinux'</span>, <span class="string">'.org'</span>)</span><br></pre></td></tr></table></figure><h4 id="split"><a href="#split" class="headerlink" title="split()"></a>split()</h4><p>从左到右通过指定分隔符对字符串进行切片,如果参数num有指定值,则仅分隔num个子字符串</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=<span class="string">"www.chenfanlinux.org"</span></span><br><span class="line"><span class="comment"># 指定切一次,以`.`来分割</span></span><br><span class="line"><span class="meta">>>> </span>string.split(<span class="string">"."</span>,<span class="number">1</span>)</span><br><span class="line">[<span class="string">'www'</span>, <span class="string">'chenfanlinux'</span>]</span><br><span class="line"><span class="comment"># 指定切二次,以`.`来分割</span></span><br><span class="line"><span class="meta">>>> </span>string.split(<span class="string">"."</span>,<span class="number">2</span>)</span><br><span class="line">[<span class="string">'www'</span>, <span class="string">'chenfanlinux'</span>, <span class="string">'org'</span>]</span><br></pre></td></tr></table></figure><h4 id="splitlines"><a href="#splitlines" class="headerlink" title="splitlines()"></a>splitlines()</h4><p>按照行分隔,返回一个包含各行作为元素的列表,如果num指定则仅切片num个行.</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 定义一个有换行的变量,`\n`可以划行</span></span><br><span class="line"><span class="meta">>>> </span>string=<span class="string">"www\nchenfanlinux\norg"</span></span><br><span class="line"><span class="comment"># 输出内容</span></span><br><span class="line"><span class="meta">>>> </span>print(string)</span><br><span class="line">www</span><br><span class="line">chenfanlinux</span><br><span class="line">org</span><br><span class="line"><span class="comment"># 把有行的转换成一个列表</span></span><br><span class="line"><span class="meta">>>> </span>string.splitlines(<span class="number">1</span>)</span><br><span class="line">[<span class="string">'www\n'</span>, <span class="string">'chenfanlinux\n'</span>, <span class="string">'org'</span>]</span><br></pre></td></tr></table></figure><h4 id="join"><a href="#join" class="headerlink" title="join()"></a>join()</h4><p>将序列中的元素以指定的字符连接生成一个新的字符串。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>string=(<span class="string">"a"</span>,<span class="string">"b"</span>,<span class="string">"c"</span>)</span><br><span class="line"><span class="meta">>>> </span><span class="string">'-'</span>.join(string)</span><br><span class="line"><span class="string">'a-b-c'</span></span><br></pre></td></tr></table></figure><h2 id="列表内建函数"><a href="#列表内建函数" class="headerlink" title="列表内建函数"></a>列表内建函数</h2><ul><li>在 <code>ipython3</code> 中定义一个 <strong>列表</strong>,例如:<code>name_list = []</code> , 输入 <code>name_list.</code> 按下 <code>TAB</code> 键,<code>ipython</code> 会提示 <strong>列表</strong> 能够使用的 <strong>方法</strong> 如下:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">In [<span class="number">1</span>]: name_list.</span><br><span class="line">name_list.append name_list.count name_list.insert name_list.reverse</span><br><span class="line">name_list.clear name_list.extend name_list.pop name_list.sort</span><br><span class="line">name_list.copy name_list.index name_list.remove</span><br></pre></td></tr></table></figure><ul><li>dir(list)</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dir(list)</span><br><span class="line">[<span class="string">'__add__'</span>, <span class="string">'__class__'</span>, <span class="string">'__contains__'</span>, <span class="string">'__delattr__'</span>, <span class="string">'__delitem__'</span>, <span class="string">'__dir__'</span>, <span class="string">'__doc__'</span>, <span class="string">'__eq__'</span>, <span class="string">'__format__'</span>, <span class="string">'__ge__'</span>, <span class="string">'__getattribute__'</span>, <span class="string">'__getitem__'</span>, <span class="string">'__gt__'</span>, <span class="string">'__hash__'</span>, <span class="string">'__iadd__'</span>, <span class="string">'__imul__'</span>, <span class="string">'__init__'</span>, <span class="string">'__iter__'</span>, <span class="string">'__le__'</span>, <span class="string">'__len__'</span>, <span class="string">'__lt__'</span>, <span class="string">'__mul__'</span>, <span class="string">'__ne__'</span>, <span class="string">'__new__'</span>, <span class="string">'__reduce__'</span>, <span class="string">'__reduce_ex__'</span>, <span class="string">'__repr__'</span>, <span class="string">'__reversed__'</span>, <span class="string">'__rmul__'</span>, <span class="string">'__setattr__'</span>, <span class="string">'__setitem__'</span>, <span class="string">'__sizeof__'</span>, <span class="string">'__str__'</span>, <span class="string">'__subclasshook__'</span>, <span class="string">'append'</span>, <span class="string">'clear'</span>, <span class="string">'copy'</span>, <span class="string">'count'</span>, <span class="string">'extend'</span>, <span class="string">'index'</span>, <span class="string">'insert'</span>, <span class="string">'pop'</span>, <span class="string">'remove'</span>, <span class="string">'reverse'</span>, <span class="string">'sort'</span>]</span><br></pre></td></tr></table></figure><table><thead><tr><th>序号</th><th>分类</th><th>关键字 / 函数 / 方法</th><th>说明</th></tr></thead><tbody><tr><td>1</td><td>增加</td><td>列表.insert(索引, 数据)</td><td>在指定位置插入数据</td></tr><tr><td>2</td><td>增加</td><td>列表.append(数据)</td><td>在末尾追加数据</td></tr><tr><td>3</td><td>增加</td><td>列表.extend(列表2)</td><td>将列表2 的数据追加到列表</td></tr><tr><td>4</td><td>修改</td><td>列表[索引] = 数据</td><td>修改指定索引的数据</td></tr><tr><td>5</td><td>删除</td><td>del 列表[索引]</td><td>删除指定索引的数据</td></tr><tr><td>6</td><td>删除</td><td>列表.remove[数据]</td><td>删除第一个出现的指定数据</td></tr><tr><td>7</td><td>删除</td><td>列表.pop</td><td>删除末尾数据</td></tr><tr><td>8</td><td>删除</td><td>列表.pop(索引)</td><td>删除指定索引数据</td></tr><tr><td>9</td><td>删除</td><td>列表.clear</td><td>清空列表</td></tr><tr><td>10</td><td>统计</td><td>len(列表)</td><td>列表长度</td></tr><tr><td>11</td><td>统计</td><td>列表.count(数据)</td><td>数据在列表中出现的次数</td></tr><tr><td>12</td><td>排序</td><td>列表.sort()</td><td>升序排序</td></tr><tr><td>13</td><td>排序</td><td>列表.sort(reverse=True)</td><td>降序排序</td></tr><tr><td>14</td><td>排序</td><td>列表.reverse()</td><td>逆序、反转</td></tr></tbody></table><h3 id="增加"><a href="#增加" class="headerlink" title="增加"></a>增加</h3><h4 id="append"><a href="#append" class="headerlink" title="append()"></a>append()</h4><p>在列表末尾添加新的对象</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list.append(<span class="string">"C#"</span>)</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>, <span class="string">'C#'</span>]</span><br></pre></td></tr></table></figure><h4 id="extend"><a href="#extend" class="headerlink" title="extend ()"></a>extend ()</h4><p>用于在列表末尾一次性追加另一个序列中的多个值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'Python'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_OS = [<span class="string">'Windows'</span>, <span class="string">'Linux'</span>, <span class="string">'Unix'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'Python'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_OS</span><br><span class="line">[<span class="string">'Windows'</span>, <span class="string">'Linux'</span>, <span class="string">'Unix'</span>]</span><br><span class="line"><span class="comment"># 把列表`name_OS`中的内容添加到`name_list`的尾部</span></span><br><span class="line"><span class="meta">>>> </span>name_list.extend(name_OS)</span><br><span class="line"><span class="comment"># 输出的结果</span></span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'Python'</span>, <span class="string">'Windows'</span>, <span class="string">'Linux'</span>, <span class="string">'Unix'</span>]</span><br></pre></td></tr></table></figure><h4 id="insert"><a href="#insert" class="headerlink" title="insert ()"></a>insert ()</h4><p>将指定对象插入列表</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="comment"># 把位置`1`的内容换成`C`,后面的自动退格一个位置</span></span><br><span class="line"><span class="meta">>>> </span>name_list.insert(<span class="number">1</span>,<span class="string">"C"</span>)</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'Python'</span>, <span class="string">'C'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br></pre></td></tr></table></figure><h3 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h3><h4 id="remove"><a href="#remove" class="headerlink" title="remove ()"></a>remove ()</h4><p>移除列表中某个值的第一个匹配项</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>, <span class="string">'Python'</span>]</span><br><span class="line"><span class="comment"># 每次删除的时候只会把第一次匹配到的值删除,第二个值不会被删除</span></span><br><span class="line"><span class="meta">>>> </span>name_list.remove(<span class="string">"Python"</span>)</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'PHP'</span>, <span class="string">'JAVA'</span>, <span class="string">'Python'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list.remove(<span class="string">"Python"</span>)</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br></pre></td></tr></table></figure><h4 id="clear"><a href="#clear" class="headerlink" title="clear()"></a>clear()</h4><p>清除列表内所有元素</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>li</span><br><span class="line">[<span class="string">'Ansheng'</span>]</span><br><span class="line"><span class="meta">>>> </span>li.clear()</span><br><span class="line"><span class="meta">>>> </span>li</span><br><span class="line">[]</span><br></pre></td></tr></table></figure><h4 id="pop"><a href="#pop" class="headerlink" title="pop()"></a>pop()</h4><p>移除列表中的一个元素,并且返回该元素的值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="comment"># 删除位置1上面的内容,并且返回删除的字符串</span></span><br><span class="line"><span class="meta">>>> </span>name_list.pop(<span class="number">1</span>)</span><br><span class="line"><span class="string">'PHP'</span></span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'Python'</span>, <span class="string">'JAVA'</span>]</span><br></pre></td></tr></table></figure><h3 id="修改"><a href="#修改" class="headerlink" title="修改"></a>修改</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>my_list = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>]</span><br><span class="line"><span class="meta">>>> </span>my_list[<span class="number">1</span>] = <span class="string">'2'</span></span><br><span class="line"><span class="meta">>>> </span>my_list</span><br><span class="line">[<span class="number">1</span>, <span class="string">'2'</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]</span><br></pre></td></tr></table></figure><h3 id="查找"><a href="#查找" class="headerlink" title="查找"></a>查找</h3><h4 id="index-1"><a href="#index-1" class="headerlink" title="index()"></a>index()</h4><p>从列表中找出某个值第一个匹配项的索引位置</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查找对象所在的位置</span></span><br><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list.index(<span class="string">"PHP"</span>)</span><br><span class="line"><span class="number">1</span></span><br></pre></td></tr></table></figure><h3 id="统计"><a href="#统计" class="headerlink" title="统计"></a>统计</h3><h4 id="count"><a href="#count" class="headerlink" title="count ()"></a>count ()</h4><p>统计某个元素在列表中出现的次数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'PHP'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list.count(<span class="string">"PHP"</span>)</span><br><span class="line"><span class="number">2</span></span><br></pre></td></tr></table></figure><h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><h4 id="reverse"><a href="#reverse" class="headerlink" title="reverse()"></a>reverse()</h4><p>反向输出列表中的元素</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list.reverse()</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'JAVA'</span>, <span class="string">'PHP'</span>, <span class="string">'Python'</span>]</span><br></pre></td></tr></table></figure><h4 id="sort"><a href="#sort" class="headerlink" title="sort ()"></a>sort ()</h4><p>对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>name_list = [<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'Python'</span>, <span class="string">'PHP'</span>, <span class="string">'JAVA'</span>]</span><br><span class="line"><span class="meta">>>> </span>name_list.sort()</span><br><span class="line"><span class="meta">>>> </span>name_list</span><br><span class="line">[<span class="string">'JAVA'</span>, <span class="string">'PHP'</span>, <span class="string">'Python'</span>]</span><br></pre></td></tr></table></figure><h3 id="复制"><a href="#复制" class="headerlink" title="复制"></a>复制</h3><h4 id="copy"><a href="#copy" class="headerlink" title="copy"></a>copy</h4><p>浅拷贝</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>my_list = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>]</span><br><span class="line"><span class="meta">>>> </span>my_list_copy = my_list.copy() <span class="comment"># 这里是浅拷贝</span></span><br><span class="line"><span class="meta">>>> </span>my_list_copy</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]</span><br><span class="line"><span class="meta">>>> </span>my_list_copy[<span class="number">0</span>] = <span class="string">'1'</span></span><br><span class="line"><span class="meta">>>> </span>my_list <span class="comment"># 不会修改</span></span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]</span><br><span class="line"><span class="meta">>>> </span>my_list_copy</span><br><span class="line">[<span class="string">'1'</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]</span><br></pre></td></tr></table></figure><h2 id="元组内建函数"><a href="#元组内建函数" class="headerlink" title="元组内建函数"></a>元组内建函数</h2><p><code>Tuple</code>(元组)与列表类似,不同之处在于元组的 <strong>元素不能修改</strong></p><ul><li><p>在 <code>ipython3</code> 中定义一个 <strong>元组</strong>,例如:<code>info = ()</code> ,输入 <code>info.</code> 按下 <code>TAB</code> 键,<code>ipython</code> 会提示 <strong>元组</strong> 能够使用的函数如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">info.count info.index</span><br></pre></td></tr></table></figure></li><li><p>dir(tuple)</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dir(tuple)</span><br><span class="line">[<span class="string">'__add__'</span>, <span class="string">'__class__'</span>, <span class="string">'__contains__'</span>, <span class="string">'__delattr__'</span>, <span class="string">'__dir__'</span>, <span class="string">'__doc__'</span>, <span class="string">'__eq__'</span>, <span class="string">'__format__'</span>, <span class="string">'__ge__'</span>, <span class="string">'__getattribute__'</span>, <span class="string">'__getitem__'</span>, <span class="string">'__getnewargs__'</span>, <span class="string">'__gt__'</span>, <span class="string">'__hash__'</span>, <span class="string">'__init__'</span>, <span class="string">'__iter__'</span>, <span class="string">'__le__'</span>, <span class="string">'__len__'</span>, <span class="string">'__lt__'</span>, <span class="string">'__mul__'</span>, <span class="string">'__ne__'</span>, <span class="string">'__new__'</span>, <span class="string">'__reduce__'</span>, <span class="string">'__reduce_ex__'</span>, <span class="string">'__repr__'</span>, <span class="string">'__rmul__'</span>, <span class="string">'__setattr__'</span>, <span class="string">'__sizeof__'</span>, <span class="string">'__str__'</span>, <span class="string">'__subclasshook__'</span>, <span class="string">'count'</span>, <span class="string">'index'</span>]</span><br></pre></td></tr></table></figure><h3 id="count-1"><a href="#count-1" class="headerlink" title="count()"></a>count()</h3><p>查看列表中元素出现的次数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>ages = tuple((<span class="number">11</span>, <span class="number">22</span>, <span class="number">33</span>, <span class="number">44</span>, <span class="number">55</span>))</span><br><span class="line"><span class="meta">>>> </span>ages</span><br><span class="line">(<span class="number">11</span>, <span class="number">22</span>, <span class="number">33</span>, <span class="number">44</span>, <span class="number">55</span>)</span><br><span class="line"><span class="meta">>>> </span>ages.count(<span class="number">11</span>)</span><br><span class="line"><span class="number">1</span></span><br></pre></td></tr></table></figure><h3 id="index-2"><a href="#index-2" class="headerlink" title="index()"></a>index()</h3><p>查找元素在元组中的位置</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>ages = tuple((<span class="number">11</span>, <span class="number">22</span>, <span class="number">33</span>, <span class="number">44</span>, <span class="number">55</span>))</span><br><span class="line"><span class="meta">>>> </span>ages.index(<span class="number">11</span>)</span><br><span class="line"><span class="number">0</span></span><br><span class="line"><span class="meta">>>> </span>ages.index(<span class="number">44</span>)</span><br><span class="line"><span class="number">3</span></span><br></pre></td></tr></table></figure><h3 id="创建空元组"><a href="#创建空元组" class="headerlink" title="创建空元组"></a>创建空元组</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">info_tuple = ()</span><br></pre></td></tr></table></figure><h3 id="一个元素元组"><a href="#一个元素元组" class="headerlink" title="一个元素元组"></a>一个元素元组</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">info_tuple = (<span class="number">50</span>, )</span><br></pre></td></tr></table></figure><h2 id="字典内建函数"><a href="#字典内建函数" class="headerlink" title="字典内建函数"></a>字典内建函数</h2><ul><li><p>在 <code>ipython3</code> 中定义一个 <strong>字典</strong>,例如:<code>xiaoming = {}</code>,输入 <code>xiaoming.</code> 按下 <code>TAB</code> 键,<code>ipython</code> 会提示 <strong>字典</strong> 能够使用的函数如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">In [<span class="number">1</span>]: xiaoming.</span><br><span class="line">xiaoming.clear xiaoming.items xiaoming.setdefault</span><br><span class="line">xiaoming.copy xiaoming.keys xiaoming.update</span><br><span class="line">xiaoming.fromkeys xiaoming.pop xiaoming.values</span><br><span class="line">xiaoming.get</span><br></pre></td></tr></table></figure></li><li><p>dir(dict)</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dir(dict)</span><br><span class="line">[<span class="string">'__class__'</span>, <span class="string">'__contains__'</span>, <span class="string">'__delattr__'</span>, <span class="string">'__delitem__'</span>, <span class="string">'__dir__'</span>, <span class="string">'__doc__'</span>, <span class="string">'__eq__'</span>, <span class="string">'__format__'</span>, <span class="string">'__ge__'</span>, <span class="string">'__getattribute__'</span>, <span class="string">'__getitem__'</span>, <span class="string">'__gt__'</span>, <span class="string">'__hash__'</span>, <span class="string">'__init__'</span>, <span class="string">'__iter__'</span>, <span class="string">'__le__'</span>, <span class="string">'__len__'</span>, <span class="string">'__lt__'</span>, <span class="string">'__ne__'</span>, <span class="string">'__new__'</span>, <span class="string">'__reduce__'</span>, <span class="string">'__reduce_ex__'</span>, <span class="string">'__repr__'</span>, <span class="string">'__setattr__'</span>, <span class="string">'__setitem__'</span>, <span class="string">'__sizeof__'</span>, <span class="string">'__str__'</span>, <span class="string">'__subclasshook__'</span>, <span class="string">'clear'</span>, <span class="string">'copy'</span>, <span class="string">'fromkeys'</span>, <span class="string">'get'</span>, <span class="string">'items'</span>, <span class="string">'keys'</span>, <span class="string">'pop'</span>, <span class="string">'popitem'</span>, <span class="string">'setdefault'</span>, <span class="string">'update'</span>, <span class="string">'values'</span>]</span><br></pre></td></tr></table></figure><h3 id="clear-1"><a href="#clear-1" class="headerlink" title="clear()"></a>clear()</h3><p>删除字典中的所有元素</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = dict({<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>})</span><br><span class="line"><span class="meta">>>> </span>person</span><br><span class="line">{<span class="string">'age'</span>: <span class="number">18</span>, <span class="string">'name'</span>: <span class="string">'ansheng'</span>}</span><br><span class="line"><span class="meta">>>> </span>person.clear()</span><br><span class="line"><span class="comment"># 清空字典的内容之后字典会变成一个空字典</span></span><br><span class="line"><span class="meta">>>> </span>person</span><br><span class="line">{}</span><br></pre></td></tr></table></figure><h3 id="copy-1"><a href="#copy-1" class="headerlink" title="copy()"></a>copy()</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = dict({<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>})</span><br><span class="line"><span class="meta">>>> </span>person.copy()</span><br><span class="line">{<span class="string">'age'</span>: <span class="number">18</span>, <span class="string">'name'</span>: <span class="string">'ansheng'</span>}</span><br></pre></td></tr></table></figure><h3 id="fromkeys"><a href="#fromkeys" class="headerlink" title="fromkeys()"></a>fromkeys()</h3><p>创建一个新字典,以序列seq中元素做字典的键,value为字典所有键对应的初始值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>seq = (<span class="string">'name'</span>, <span class="string">'age'</span>, <span class="string">'sex'</span>)</span><br><span class="line"><span class="meta">>>> </span>dict = dict.fromkeys(seq)</span><br><span class="line"><span class="meta">>>> </span>dict</span><br><span class="line">{<span class="string">'age'</span>: <span class="keyword">None</span>, <span class="string">'name'</span>: <span class="keyword">None</span>, <span class="string">'sex'</span>: <span class="keyword">None</span>}</span><br></pre></td></tr></table></figure><h3 id="get"><a href="#get" class="headerlink" title="get()"></a>get()</h3><p>返回指定键的值,如果值不在字典中返回默认值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = {<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>}</span><br><span class="line"><span class="meta">>>> </span>person.get(<span class="string">"name"</span>)</span><br><span class="line"><span class="string">'ansheng'</span></span><br></pre></td></tr></table></figure><h3 id="items"><a href="#items" class="headerlink" title="items()"></a>items()</h3><p>以列表返回可遍历的(键, 值)元组数组</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = {<span class="string">"name"</span>: <span class="string">"mr.wu"</span>, <span class="string">'age'</span>: <span class="number">18</span>}</span><br><span class="line"><span class="comment"># 以元组的方式输出出来</span></span><br><span class="line"><span class="meta">>>> </span>person.items()</span><br><span class="line">[(<span class="string">'age'</span>, <span class="number">18</span>), (<span class="string">'name'</span>, <span class="string">'mr.wu'</span>)]</span><br></pre></td></tr></table></figure><h3 id="keys"><a href="#keys" class="headerlink" title="keys()"></a>keys()</h3><p>以列表的形式返回一个字典所有的键</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = {<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>}</span><br><span class="line"><span class="meta">>>> </span>person.keys()</span><br><span class="line">[<span class="string">'age'</span>, <span class="string">'name'</span>]</span><br></pre></td></tr></table></figure><h3 id="pop-1"><a href="#pop-1" class="headerlink" title="pop()"></a>pop()</h3><p>删除指定给定键所对应的值,返回这个值并从字典中把它移除</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = {<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>}</span><br><span class="line"><span class="meta">>>> </span>person</span><br><span class="line">{<span class="string">'age'</span>: <span class="number">18</span>, <span class="string">'name'</span>: <span class="string">'ansheng'</span>}</span><br><span class="line"><span class="comment"># 返回删除键对应的值</span></span><br><span class="line"><span class="meta">>>> </span>person.pop(<span class="string">"age"</span>)</span><br><span class="line"><span class="number">18</span></span><br><span class="line"><span class="meta">>>> </span>person</span><br><span class="line">{<span class="string">'name'</span>: <span class="string">'ansheng'</span>}</span><br></pre></td></tr></table></figure><h3 id="popitem"><a href="#popitem" class="headerlink" title="popitem()"></a>popitem()</h3><p>随机返回并删除字典中的一对键和值,因为字典是无序的,没有所谓的”最后一项”或是其它顺序。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = {<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>}</span><br><span class="line"><span class="comment"># 随即删除并显示所删除的键和值</span></span><br><span class="line"><span class="meta">>>> </span>person.popitem()</span><br><span class="line">(<span class="string">'age'</span>, <span class="number">18</span>)</span><br><span class="line"><span class="meta">>>> </span>person</span><br><span class="line">{<span class="string">'name'</span>: <span class="string">'ansheng'</span>}</span><br></pre></td></tr></table></figure><h3 id="setdefault"><a href="#setdefault" class="headerlink" title="setdefault()"></a>setdefault()</h3><p>如果key不存在,则创建,如果存在,则返回已存在的值且不修改</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = {<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>}</span><br><span class="line"><span class="comment"># 如果字典中有这个键,那么就输出这个键的值</span></span><br><span class="line"><span class="meta">>>> </span>person.setdefault(<span class="string">"name"</span>)</span><br><span class="line"><span class="string">'ansheng'</span></span><br><span class="line"><span class="comment"># 如果没有则不输出,但是会创建一个键,值为默认的'None',值是可以指定的</span></span><br><span class="line"><span class="meta">>>> </span>person.setdefault(<span class="string">"sex"</span>)</span><br><span class="line"><span class="meta">>>> </span>person</span><br><span class="line">{<span class="string">'age'</span>: <span class="number">18</span>, <span class="string">'name'</span>: <span class="string">'ansheng'</span>, <span class="string">'sex'</span>: <span class="keyword">None</span>}</span><br></pre></td></tr></table></figure><h3 id="update"><a href="#update" class="headerlink" title="update()"></a>update()</h3><p>把字典dic2的键/值对更新到dic1里</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dic1 = {<span class="string">"name"</span>:<span class="string">"ansheng"</span>}</span><br><span class="line"><span class="meta">>>> </span>dic2 = {<span class="string">"age"</span>:<span class="string">"18"</span>}</span><br><span class="line"><span class="meta">>>> </span>dic1</span><br><span class="line">{<span class="string">'name'</span>: <span class="string">'ansheng'</span>}</span><br><span class="line"><span class="meta">>>> </span>dic2</span><br><span class="line">{<span class="string">'age'</span>: <span class="string">'18'</span>}</span><br><span class="line"><span class="meta">>>> </span>dic1.update(dic2)</span><br><span class="line"><span class="meta">>>> </span>dic1</span><br><span class="line">{<span class="string">'age'</span>: <span class="string">'18'</span>, <span class="string">'name'</span>: <span class="string">'ansheng'</span>}</span><br></pre></td></tr></table></figure><h3 id="values"><a href="#values" class="headerlink" title="values()"></a>values()</h3><p>显示字典中所有的值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>person = {<span class="string">"name"</span>: <span class="string">"ansheng"</span>, <span class="string">'age'</span>: <span class="number">18</span>}</span><br><span class="line"><span class="meta">>>> </span>person.values()</span><br><span class="line">[<span class="number">18</span>, <span class="string">'ansheng'</span>]</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="内建函数引言"><a href="#内建函数引言" class="headerlink" title="内建函数引言"></a>内建函数引言</h2><blockquote>
<p>Python内建函数按分类可以分为系统内建函数和内置对象(字符串,列表,字典,set,文件对象)的方法,下面我们将带您认识系统内建函数和内置数据对象的方法。</p>
</blockquote>
<ul>
<li>系统内建函数</li>
<li>内置对象方法<ul>
<li>str字符</li>
<li>list列表</li>
<li>tuple元组</li>
<li>dict字典</li>
<li>set集合</li>
</ul>
</li>
</ul>
<h2 id="系统内建函数"><a href="#系统内建函数" class="headerlink" title="系统内建函数"></a>系统内建函数</h2><blockquote>
<p>查看官方文档: <a href="https://docs.python.org/3/library/functions.html" target="_blank" rel="noopener">python系统内建函数</a></p>
</blockquote>
<p><img src="https://s1.ax1x.com/2018/05/19/Cc0kKP.png" alt="Python系统内建函数图"></p>
<h3 id="dir"><a href="#dir" class="headerlink" title="dir()"></a>dir()</h3><ul>
<li><p>作用:返回一个对象中中的所有方法 </p>
</li>
<li><p>使用方法:dir([object]) </p>
</li>
<li><p>返回值:list of strings </p>
</li>
</ul>
<p>实例说明:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>dir(str) <span class="comment"># 查找str类型对象所对应的方法</span></span><br><span class="line">[<span class="string">'__add__'</span>, <span class="string">'__class__'</span>, <span class="string">'__contains__'</span>, <span class="string">'__delattr__'</span>, <span class="string">'__dir__'</span>, <span class="string">'__doc__'</span>, <span class="string">'__eq__'</span>, <span class="string">'__format__'</span>, <span class="string">'__ge__'</span>, <span class="string">'__getattribute__'</span>, <span class="string">'__getitem__'</span>, <span class="string">'__getnewargs__'</span>, <span class="string">'__gt__'</span>, <span class="string">'__hash__'</span>, <span class="string">'__init__'</span>, <span class="string">'__iter__'</span>, <span class="string">'__le__'</span>, <span class="string">'__len__'</span>, <span class="string">'__lt__'</span>, <span class="string">'__mod__'</span>, <span class="string">'__mul__'</span>, <span class="string">'__ne__'</span>, <span class="string">'__new__'</span>, <span class="string">'__reduce__'</span>, <span class="string">'__reduce_ex__'</span>, <span class="string">'__repr__'</span>, <span class="string">'__rmod__'</span>, <span class="string">'__rmul__'</span>, <span class="string">'__setattr__'</span>, <span class="string">'__sizeof__'</span>, <span class="string">'__str__'</span>, <span class="string">'__subclasshook__'</span>, <span class="string">'capitalize'</span>, <span class="string">'casefold'</span>, <span class="string">'center'</span>, <span class="string">'count'</span>, <span class="string">'encode'</span>, <span class="string">'endswith'</span>, <span class="string">'expandtabs'</span>, <span class="string">'find'</span>, <span class="string">'format'</span>, <span class="string">'format_map'</span>, <span class="string">'index'</span>, <span class="string">'isalnum'</span>, <span class="string">'isalpha'</span>, <span class="string">'isdecimal'</span>, <span class="string">'isdigit'</span>, <span class="string">'isidentifier'</span>, <span class="string">'islower'</span>, <span class="string">'isnumeric'</span>, <span class="string">'isprintable'</span>, <span class="string">'isspace'</span>, <span class="string">'istitle'</span>, <span class="string">'isupper'</span>, <span class="string">'join'</span>, <span class="string">'ljust'</span>, <span class="string">'lower'</span>, <span class="string">'lstrip'</span>, <span class="string">'maketrans'</span>, <span class="string">'partition'</span>, <span class="string">'replace'</span>, <span class="string">'rfind'</span>, <span class="string">'rindex'</span>, <span class="string">'rjust'</span>, <span class="string">'rpartition'</span>, <span class="string">'rsplit'</span>, <span class="string">'rstrip'</span>, <span class="string">'split'</span>, <span class="string">'splitlines'</span>, <span class="string">'startswith'</span>, <span class="string">'strip'</span>, <span class="string">'swapcase'</span>, <span class="string">'title'</span>, <span class="string">'translate'</span>, <span class="string">'upper'</span>, <span class="string">'zfill'</span>]</span><br></pre></td></tr></table></figure>
</summary>
<category term="python基础知识" scheme="http://www.chenfanlinux.org/categories/python%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/"/>
<category term="Python" scheme="http://www.chenfanlinux.org/tags/Python/"/>
</entry>
<entry>
<title>自动化运维工具Fabric</title>
<link href="http://www.chenfanlinux.org/2018/05/31/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E5%B7%A5%E5%85%B7Fabric/"/>
<id>http://www.chenfanlinux.org/2018/05/31/自动化运维工具Fabric/</id>
<published>2018-05-31T09:59:47.000Z</published>
<updated>2018-05-31T10:01:34.000Z</updated>
<content type="html"><项目地址的可以发现,其版本号直接从1.14到了2.0版本,研究源码可以发现,其使用发现发生了很大的变化,今天记录此文章,对比一下这两种版本的升级之旅。</p><p><img src="https://s1.ax1x.com/2018/05/31/CIZHne.png" alt="Fabirc的git地址"></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ yum install python-pip</span><br><span class="line">$ pip install --upgrade pip</span><br><span class="line">$ pip install fabric==<span class="number">1.14</span><span class="number">.0</span> <span class="comment"># 指定版本安装,这里如果不指定的话,安装最新版本</span></span><br></pre></td></tr></table></figure><a id="more"></a><h2 id="Fabric-1-x版本-入门示例"><a href="#Fabric-1-x版本-入门示例" class="headerlink" title="Fabric 1.x版本 入门示例"></a>Fabric 1.x版本 入门示例</h2><p><strong>使用方法:</strong></p><p>部署脚本fabfile.py(名字不能变)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#fabfile.py 脚本名</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding:utf-8 _*_</span></span><br><span class="line"><span class="keyword">from</span> fabric.api <span class="keyword">import</span> run</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">host_type</span><span class="params">()</span>:</span></span><br><span class="line"> run(<span class="string">'uname -s'</span>)</span><br></pre></td></tr></table></figure><p><strong>启动:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">[root@test-node01 ~]<span class="comment"># fab -H 127.0.0.1 host_type</span></span><br><span class="line">[<span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>] Executing task <span class="string">'host_type'</span></span><br><span class="line">[<span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>] run: uname -s</span><br><span class="line">[<span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>] out: Linux</span><br><span class="line">[<span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>] out:</span><br><span class="line">Done.</span><br><span class="line">Disconnecting <span class="keyword">from</span> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>... done.</span><br></pre></td></tr></table></figure><h3 id="fabric常用参数"><a href="#fabric常用参数" class="headerlink" title="fabric常用参数"></a>fabric常用参数</h3><ul><li>-l : 显示定义好的任务函数名</li><li>-f : 指定fab入口文件,默认入口文件名为fabfile.py</li><li>-H : 指定目标主机,多台主机用”,”号分割</li></ul><h3 id="fabric常用API"><a href="#fabric常用API" class="headerlink" title="fabric常用API"></a>fabric常用API</h3><ul><li>local : 执行本地命令,如:local(‘uname -s’)</li><li>lcd : 切换本地目录,如:lcd(‘/home’)</li><li>cd : 切换远程目录,如:cd(‘/etc’)</li><li>run : 执行远程命令,如:run(‘free -m’)</li><li>sudo : sudo方式执行远程命令,如:sudo(‘touch /abc’)</li><li>put : 上传本地文件到远程主机,如:put(‘/hello’, ‘/home/itcast/hello’)</li><li>get : 从远程主机下载文件到本地,如:get(‘/home/python/world’, ‘/home/itcast/world’)</li><li>reboot : 重启远程主机,如:reboot()</li><li>@task : 函数装饰器,标识的函数为fab可调用的,非标记的对fab不可见,纯业务逻辑</li><li>@runs_once : 函数装饰器,标识的函数只会执行一次,不受多台主机影响</li></ul><h3 id="fabric全局属性设定"><a href="#fabric全局属性设定" class="headerlink" title="fabric全局属性设定"></a>fabric全局属性设定</h3><ul><li>env.host : 定义目标主机,如:env.host=[‘192.168.17.192’, ‘192.168.17.193’]</li><li>env.user : 定义用户名,如:env.user=”root”</li><li>env.port : 定义目标主机端口,默认为22,如:env.port=”22”</li><li>env.password : 定义密码,如:env.password=”chuanzhi”</li><li>env.passwords : 不同的主机不同的密码,如:env.passwords={‘itcast@192.168.17.192:22’:’chuanzhi’, ‘itcast@192.168.17.193:22’:’python’}</li></ul><h2 id="Fabric-1-x使用范例"><a href="#Fabric-1-x使用范例" class="headerlink" title="Fabric 1.x使用范例"></a>Fabric 1.x使用范例</h2><h3 id="示例1:动态获取远程目录列表"><a href="#示例1:动态获取远程目录列表" class="headerlink" title="示例1:动态获取远程目录列表"></a>示例1:动态获取远程目录列表</h3><p><strong>脚本:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding:utf8 _*_</span></span><br><span class="line"><span class="keyword">from</span> fabric.api <span class="keyword">import</span> *</span><br><span class="line"><span class="comment"># 登录的主机名和主机,我这里用的免密码登录</span></span><br><span class="line">env.user = <span class="string">'root'</span></span><br><span class="line">env.hosts=[<span class="string">'test-master01'</span>, <span class="string">'test-node01'</span>, <span class="string">'test-node02'</span>]</span><br><span class="line"><span class="meta">@runs_once # 函数装饰器,标识的函数只会执行一次,不受多台主机影响</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">input_raw</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">return</span> prompt(<span class="string">"please input directory name:"</span>, default=<span class="string">"/home"</span>)</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">workask</span><span class="params">(dirname)</span>:</span></span><br><span class="line"> run(<span class="string">'ls -l '</span> + dirname)</span><br><span class="line"><span class="meta">@task # 函数装饰器,标识的函数为fab可调用的,非标记的对fab不可见,纯业务逻辑</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">go</span><span class="params">()</span>:</span></span><br><span class="line"> print(<span class="string">'start ...'</span>)</span><br><span class="line"> getdirname = input_raw()</span><br><span class="line"> workask(getdirname)</span><br><span class="line"> print(<span class="string">'end ...'</span>)</span><br></pre></td></tr></table></figure><p><strong>运行:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">(chenfanlinux) [root@test-node01 test]<span class="comment"># fab go # 运行即可</span></span><br><span class="line">[test-master01] Executing task <span class="string">'go'</span></span><br><span class="line">start ...</span><br><span class="line">please input directory name: [/home] /root</span><br><span class="line">[test-master01] run: ls -l /root</span><br><span class="line">[test-master01] out: total <span class="number">0</span></span><br><span class="line">[test-master01] out:</span><br><span class="line"></span><br><span class="line">end ...</span><br><span class="line">[test-node01] Executing task <span class="string">'go'</span></span><br><span class="line">start ...</span><br><span class="line">[test-node01] run: ls -l /root</span><br><span class="line">[test-node01] out: total <span class="number">8</span></span><br><span class="line">[test-node01] out: -rw-r--r-- <span class="number">1</span> root root <span class="number">111</span> May <span class="number">31</span> <span class="number">16</span>:<span class="number">39</span> fabfile.py</span><br><span class="line">[test-node01] out: -rw-r--r-- <span class="number">1</span> root root <span class="number">299</span> May <span class="number">31</span> <span class="number">16</span>:<span class="number">39</span> fabfile.pyc</span><br><span class="line">[test-node01] out:</span><br><span class="line"></span><br><span class="line">end ...</span><br><span class="line">[test-node02] Executing task <span class="string">'go'</span></span><br><span class="line">start ...</span><br><span class="line">[test-node02] run: ls -l /root</span><br><span class="line">[test-node02] out: total <span class="number">0</span></span><br><span class="line">[test-node02] out:</span><br><span class="line"></span><br><span class="line">end ...</span><br><span class="line"></span><br><span class="line">Done.</span><br><span class="line">Disconnecting <span class="keyword">from</span> test-node02... done.</span><br><span class="line">Disconnecting <span class="keyword">from</span> test-master01... done.</span><br><span class="line">Disconnecting <span class="keyword">from</span> test-node01... done.</span><br></pre></td></tr></table></figure><h3 id="示例2:上传文件并执行"><a href="#示例2:上传文件并执行" class="headerlink" title="示例2:上传文件并执行"></a>示例2:上传文件并执行</h3><p><strong>脚本:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding:utf8 _*_</span></span><br><span class="line"><span class="keyword">from</span> fabric.api <span class="keyword">import</span> *</span><br><span class="line"><span class="comment"># 登录的主机名和主机,我这里用的免密码登录</span></span><br><span class="line">env.user = <span class="string">'root'</span></span><br><span class="line">env.hosts=[<span class="string">'test-master01'</span>, <span class="string">'test-node02'</span>]</span><br><span class="line"></span><br><span class="line"><span class="meta">@task # 切换到本地/root目录, 并打包</span></span><br><span class="line"><span class="meta">@runs_once # 这个任务执行一次</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">tar_task</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">with</span> lcd(<span class="string">'/root'</span>):</span><br><span class="line"> local(<span class="string">'tar zcvf hello.tar.gz hello.py'</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@task # 创建 远程 /home/test目录 ,并将本地的tar包上传到远程</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">put_task</span><span class="params">()</span>:</span> <span class="comment"># 这个任务将执行多次</span></span><br><span class="line"> run(<span class="string">'mkdir -p /home/test'</span>)</span><br><span class="line"> <span class="keyword">with</span> cd(<span class="string">'/home/test'</span>):</span><br><span class="line"> put(<span class="string">'/root/hello.tar.gz'</span>, <span class="string">'/home/test'</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@task # 检验本地和远程文件的md5值</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">check_task</span><span class="params">()</span>:</span> <span class="comment"># 这个任务执行多次</span></span><br><span class="line"> lmd5 = local(<span class="string">'md5sum /root/hello.tar.gz'</span>, capture=<span class="keyword">True</span>).split(<span class="string">' '</span>)[<span class="number">0</span>]</span><br><span class="line"> rmd5 = run(<span class="string">'md5sum /home/test/hello.tar.gz'</span>).split(<span class="string">' '</span>)[<span class="number">0</span>]</span><br><span class="line"> <span class="keyword">if</span> lmd5 == rmd5:</span><br><span class="line"> print(<span class="string">'OK ...'</span>)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">'ERROR ...'</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">@task # 执行本地上传的tar包中的hello.py文件</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">run_task</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">with</span> cd(<span class="string">'/home/test'</span>):</span><br><span class="line"> run(<span class="string">'tar zxvf hello.tar.gz'</span>)</span><br><span class="line"> run(<span class="string">'python hello.py'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@task</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">go</span><span class="params">()</span>:</span></span><br><span class="line"> tar_task()</span><br><span class="line"> put_task()</span><br><span class="line"> check_task()</span><br><span class="line"> run_task()</span><br></pre></td></tr></table></figure><p><strong>运行:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">(chenfanlinux) [root@test-node01 test]<span class="comment"># fab go</span></span><br><span class="line"></span><br><span class="line">--------------------------------- test-master01 -----------------------------------</span><br><span class="line">[test-master01] Executing task <span class="string">'go'</span></span><br><span class="line">[localhost] local: tar zcvf hello.tar.gz hello.py <span class="comment"># 本地打包</span></span><br><span class="line">hello.py</span><br><span class="line">[test-master01] run: mkdir -p /home/test <span class="comment"># 远程建目录</span></span><br><span class="line">[test-master01] put: /root/hello.tar.gz -> /home/test/hello.tar.gz # 本地宝上传到远程</span><br><span class="line">[localhost] local: md5sum /root/hello.tar.gz</span><br><span class="line">[test-master01] run: md5sum /home/test/hello.tar.gz <span class="comment"># 校验md5值</span></span><br><span class="line">[test-master01] out: <span class="number">9897</span>a7ad1211a72d8b9c21d8cb5d9f1e /home/test/hello.tar.gz</span><br><span class="line">[test-master01] out:</span><br><span class="line"></span><br><span class="line">OK ...</span><br><span class="line">[test-master01] run: tar zxvf hello.tar.gz <span class="comment"># 远程解包</span></span><br><span class="line">[test-master01] out: hello.py</span><br><span class="line">[test-master01] out:</span><br><span class="line"></span><br><span class="line">[test-master01] run: python hello.py <span class="comment"># 远程执行脚本</span></span><br><span class="line">[test-master01] out: Hello,Welcome to my blog www.chenfanlinux.org!</span><br><span class="line">[test-master01] out:</span><br><span class="line"></span><br><span class="line">------------------------------------- test-node02 -----------------------------------</span><br><span class="line">[test-node02] Executing task <span class="string">'go'</span></span><br><span class="line">[test-node02] run: mkdir -p /home/test</span><br><span class="line">[test-node02] put: /root/hello.tar.gz -> /home/test/hello.tar.gz</span><br><span class="line">[localhost] local: md5sum /root/hello.tar.gz</span><br><span class="line">[test-node02] run: md5sum /home/test/hello.tar.gz</span><br><span class="line">[test-node02] out: <span class="number">9897</span>a7ad1211a72d8b9c21d8cb5d9f1e /home/test/hello.tar.gz</span><br><span class="line">[test-node02] out:</span><br><span class="line"></span><br><span class="line">OK ...</span><br><span class="line">[test-node02] run: tar zxvf hello.tar.gz</span><br><span class="line">[test-node02] out: hello.py</span><br><span class="line">[test-node02] out:</span><br><span class="line"></span><br><span class="line">[test-node02] run: python hello.py</span><br><span class="line">[test-node02] out: Hello,Welcome to my blog www.chenfanlinux.org!</span><br><span class="line">[test-node02] out:</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Done.</span><br><span class="line">Disconnecting <span class="keyword">from</span> test-node02... done.</span><br><span class="line">Disconnecting <span class="keyword">from</span> test-master01... done.</span><br></pre></td></tr></table></figure><h2 id="Fabric-2-x-使用范例"><a href="#Fabric-2-x-使用范例" class="headerlink" title="Fabric 2.x 使用范例"></a>Fabric 2.x 使用范例</h2><p><strong>脚本:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># _*_ coding:utf8 _*_</span></span><br><span class="line"><span class="keyword">from</span> fabric <span class="keyword">import</span> Connection, SerialGroup</span><br><span class="line"><span class="comment"># 单个连接</span></span><br><span class="line">simple_conn = Connection(<span class="string">'test-master01'</span>)</span><br><span class="line"><span class="comment"># 多个连接</span></span><br><span class="line">many_conn = SerialGroup(<span class="string">'test-master01'</span>, <span class="string">'test-node01'</span>, <span class="string">'test-node02'</span>)</span><br><span class="line"><span class="comment"># 查看单个磁盘容量</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">disk_free</span><span class="params">(c)</span>:</span></span><br><span class="line"> <span class="string">'''</span></span><br><span class="line"><span class="string"> c : 单个连接</span></span><br><span class="line"><span class="string"> '''</span></span><br><span class="line"> uname = c.run(<span class="string">'uname -s'</span>, hide=<span class="keyword">True</span>).stdout</span><br><span class="line"> <span class="keyword">if</span> <span class="string">'Linux'</span> <span class="keyword">in</span> uname:</span><br><span class="line"> command = <span class="string">"df -h / | tail -n1 | awk '{print $5}'"</span></span><br><span class="line"> <span class="keyword">return</span> c.run(command, hide=<span class="keyword">True</span>).stdout.strip()</span><br><span class="line"> err = <span class="string">"No idea how to get disk space on {}!"</span>.format(uname)</span><br><span class="line"> <span class="keyword">raise</span> Exit(err)</span><br><span class="line"></span><br><span class="line">result = {i.host :disk_free(i) <span class="keyword">for</span> i <span class="keyword">in</span> many_conn}</span><br><span class="line"><span class="keyword">for</span> k,v <span class="keyword">in</span> result.items():</span><br><span class="line"> print(<span class="string">'主机名是{},磁盘利用率是{}'</span>.format(k,v))</span><br></pre></td></tr></table></figure><p><strong>运行:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">(chenfanlinux) [root@test-master01 test]<span class="comment"># python fabfile.py</span></span><br><span class="line"></span><br><span class="line">主机名是test-master01,磁盘利用率是<span class="number">16</span>%</span><br><span class="line">主机名是test-node01,磁盘利用率是<span class="number">13</span>%</span><br><span class="line">主机名是test-node02,磁盘利用率是<span class="number">11</span>%</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<blockquote>
<p>项目发布和运维的工作相当机械,频率还蛮高,导致时间浪费在敲大量重复的命令上。其中郁闷的是,每次操作都是相同的,命令一样,要命的是在多个机器上,很难在本机一个脚本搞定,主要时间都浪费在ssh,敲命令上了,写成脚本,完全可以一键执行,花两分钟看下执行结果。 如果你会Python的话,使用Fabric是一个很好的选择!</p>
</blockquote>
<h2 id="安装Fabric"><a href="#安装Fabric" class="headerlink" title="安装Fabric"></a>安装Fabric</h2><p>从 <a href="[Fabric项目地址](https://github.com/fabric/fabric/tree/2.1">Fabric</a>)项目地址的可以发现,其版本号直接从1.14到了2.0版本,研究源码可以发现,其使用发现发生了很大的变化,今天记录此文章,对比一下这两种版本的升级之旅。</p>
<p><img src="https://s1.ax1x.com/2018/05/31/CIZHne.png" alt="Fabirc的git地址"></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ yum install python-pip</span><br><span class="line">$ pip install --upgrade pip</span><br><span class="line">$ pip install fabric==<span class="number">1.14</span><span class="number">.0</span> <span class="comment"># 指定版本安装,这里如果不指定的话,安装最新版本</span></span><br></pre></td></tr></table></figure>
</summary>
<category term="运维自动化工具" scheme="http://www.chenfanlinux.org/categories/%E8%BF%90%E7%BB%B4%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7/"/>
<category term="Fabric" scheme="http://www.chenfanlinux.org/tags/Fabric/"/>
</entry>
<entry>
<title>Python操作MongoDB</title>
<link href="http://www.chenfanlinux.org/2018/05/28/Python%E6%93%8D%E4%BD%9CMongoDB/"/>
<id>http://www.chenfanlinux.org/2018/05/28/Python操作MongoDB/</id>
<published>2018-05-28T03:37:40.000Z</published>
<updated>2018-06-04T10:26:37.000Z</updated>
<content type="html"><</li><li>pymongo 3.4.0</li></ul><h3 id="连接MongDB"><a href="#连接MongDB" class="headerlink" title="连接MongDB"></a>连接MongDB</h3><p>连接MongoDB时,我们需要使用PyMongo库里面的<code>MongoClient</code>。一般来说,传入MongoDB的IP及端口即可,其中第一个参数为地址<code>host</code>,第二个参数为端口<code>port</code>(如果不给它传递参数,默认是27017) 。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">import</span> pymongo</span><br><span class="line"><span class="comment"># 创建MongoDB的连接对象</span></span><br><span class="line"><span class="meta">>>> </span>client = pymongo.MongoClient(host=<span class="string">'localhost'</span>, port=<span class="number">27017</span>)</span><br></pre></td></tr></table></figure><h3 id="指定数据库和集合"><a href="#指定数据库和集合" class="headerlink" title="指定数据库和集合"></a>指定数据库和集合</h3><p>MongoDB中可以建立多个数据库,接下来我们需要指定操作哪个数据库;MongoDB的每个数据库又包含许多集合(collection),它们类似于关系型数据库中的表。下一步需要指定要操作的集合,这里指定一个集合名称为students。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建或者指定数据库db</span></span><br><span class="line"><span class="meta">>>> </span>db = client[<span class="string">'test'</span>]</span><br><span class="line"><span class="meta">>>> </span>db = client.test <span class="comment"># 这种方式也可以指定数据库db</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建或者指定集合</span></span><br><span class="line"><span class="meta">>>> </span>collection = db[<span class="string">'students'</span>]</span><br><span class="line"><span class="meta">>>> </span>collection = db.students <span class="comment"># 这种方式也可以指定集合</span></span><br><span class="line"><span class="comment"># 这样我们便声明了一个Collection对象。</span></span><br></pre></td></tr></table></figure><h3 id="插入数据"><a href="#插入数据" class="headerlink" title="插入数据"></a>插入数据</h3><h4 id="插入单条数据"><a href="#插入单条数据" class="headerlink" title="插入单条数据"></a>插入单条数据</h4><p>直接调用<code>collection</code>的<code>insert()</code>方法即可插入数据</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 新建一条学生数据,这条数据以字典形式表示</span></span><br><span class="line"><span class="meta">>>> </span>student = {</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'20170101'</span>,</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'Jordan'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">20</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span></span><br><span class="line">}</span><br><span class="line"><span class="comment"># 往集合中插入数据</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.insert(student)</span><br><span class="line"><span class="meta">>>> </span>print(result) <span class="comment"># 返回insert后的 _id</span></span><br><span class="line"><span class="number">5</span>b02a3868c08d32b90ff9954</span><br></pre></td></tr></table></figure><p>在MongoDB中,每条数据其实都有一个<code>_id</code>属性来唯一标识。如果没有显式指明该属性,MongoDB会自动产生一个<code>ObjectId</code>类型的<code>_id</code>属性。<code>insert()</code>方法会在执行后返回<code>_id</code>值。</p><h4 id="插入多条数据"><a href="#插入多条数据" class="headerlink" title="插入多条数据"></a>插入多条数据</h4><p>当然,我们也可以同时插入多条数据,只需要以列表形式传递即可 。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>student1 = {</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'20170101'</span>,</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'Jordan'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">20</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>student2 = {</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'20170202'</span>,</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'Mike'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">21</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>result = collection.insert([student1, student2])</span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line">[ObjectId(<span class="string">'5b037d818c08d31574a6bd21'</span>), ObjectId(<span class="string">'5b037d818c08d31574a6bd22'</span>)]</span><br></pre></td></tr></table></figure><p>实际上,在PyMongo 3.x版本中,官方已经不推荐使用<code>insert()</code>方法了。当然,继续使用也没有什么问题。官方推荐使用<code>insert_one()</code>和<code>insert_many()</code>方法来分别插入单条记录和多条记录 。</p><a id="more"></a><h4 id="insert-one"><a href="#insert-one" class="headerlink" title="insert_one()"></a>insert_one()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>student = {</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'20170101'</span>,</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'Jordan'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">20</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment"># 插入单条数据 insert_one</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.insert_one(student)</span><br><span class="line">print(result)</span><br><span class="line"><pymongo.results.InsertOneResult object at <span class="number">0x0000000003AF8090</span>></span><br><span class="line"><span class="meta">>>> </span>print(result.inserted_id)</span><br><span class="line"><span class="number">5</span>b037e428c08d31574a6bd23</span><br><span class="line"></span><br><span class="line"><span class="comment"># 与insert()方法不同,这次返回的是InsertOneResult对象,我们可以调用其inserted_id属性获取ObjectId</span></span><br></pre></td></tr></table></figure><h4 id="insert-many"><a href="#insert-many" class="headerlink" title="insert_many()"></a>insert_many()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>student1 = { <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'Jordan'</span>, <span class="string">'age'</span>: <span class="number">20</span>, <span class="string">'gender'</span>: <span class="string">'male'</span> }</span><br><span class="line">>>></span><br><span class="line"><span class="meta">>>> </span>student2 = { <span class="string">'id'</span>: <span class="string">'20170202'</span>, <span class="string">'name'</span>: <span class="string">'Mike'</span>, <span class="string">'age'</span>: <span class="number">21</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span> }</span><br><span class="line"><span class="comment"># insert_many 插入多条数据</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.insert_many([student1, student2])</span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line"><pymongo.results.InsertManyResult object at <span class="number">0x0000000003AF82D0</span>></span><br><span class="line"><span class="meta">>>> </span>print(result.inserted_ids)</span><br><span class="line">[ObjectId(<span class="string">'5b037fab8c08d31574a6bd24'</span>), ObjectId(<span class="string">'5b037fab8c08d31574a6bd25'</span>)]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 该方法返回的类型是InsertManyResult,调用inserted_ids属性可以获取插入数据的_id列表。</span></span><br></pre></td></tr></table></figure><h3 id="查询数据"><a href="#查询数据" class="headerlink" title="查询数据"></a>查询数据</h3><p>插入数据后,我们可以利用<code>find_one()</code>或<code>find()</code>方法进行查询,其中<code>find_one()</code>查询得到的是单个结果,<code>find()</code>则返回一个生成器对象。</p><h4 id="find-one"><a href="#find-one" class="headerlink" title="find_one()"></a>find_one()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>result = collection.find_one({<span class="string">'name'</span>: <span class="string">'Mike'</span>}) <span class="comment"># 查询单个结果</span></span><br><span class="line"><span class="meta">>>> </span>print(type(result)) <span class="comment"># 类型为字典</span></span><br><span class="line"><<span class="class"><span class="keyword">class</span> '<span class="title">dict</span>'></span></span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"># 这里我们查询<span class="title">name</span>为<span class="title">Mike</span>的数据,它的返回结果是字典类型</span></span><br><span class="line"><span class="class">>>> <span class="title">print</span><span class="params">(result)</span></span></span><br><span class="line">{'_id': ObjectId('5b037d818c08d31574a6bd22'), 'id': '20170202', 'name': 'Mike', 'age': 21, 'gender': 'male'}</span><br><span class="line"><span class="comment"># 可以发现,它多了_id属性,这就是MongoDB在插入过程中自动添加的。</span></span><br></pre></td></tr></table></figure><p>此外,我们也可以根据<code>ObjectId</code>来查询,此时需要使用bson库里面的<code>objectid</code>:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">from</span> bson.objectid <span class="keyword">import</span> ObjectId</span><br><span class="line"><span class="comment"># 根据ObjectId来查找</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.find_one({<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037fab8c08d31574a6bd24'</span>)})</span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037fab8c08d31574a6bd24'</span>), <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'Jordan'</span>, <span class="string">'age'</span>: <span class="number">20</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line"><span class="comment"># 当然,如果查询结果不存在,则会返回None。</span></span><br></pre></td></tr></table></figure><h4 id="find"><a href="#find" class="headerlink" title="find()"></a>find()</h4><p>对于多条数据的查询,我们可以使用<code>find()</code>方法。例如,这里查找年龄为20的数据,示例如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>results = collection.find({<span class="string">'age'</span>: <span class="number">20</span>})</span><br><span class="line"><span class="meta">>>> </span>print(results)</span><br><span class="line"><pymongo.cursor.Cursor object at <span class="number">0x00000000038D1E48</span>></span><br><span class="line"><span class="comment"># 返回结果是Cursor类型,它相当于一个生成器,我们需要遍历取到所有的结果,其中每个结果都是字典类型。</span></span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> result <span class="keyword">in</span> results:</span><br><span class="line"><span class="meta">... </span> print(result)</span><br><span class="line">...</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037d008c08d31574a6bd20'</span>), <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'Jordan'</span>, <span class="string">'age'</span>: <span class="number">20</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037d818c08d31574a6bd21'</span>), <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'Jordan'</span>, <span class="string">'age'</span>: <span class="number">20</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037e428c08d31574a6bd23'</span>), <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'Jordan'</span>, <span class="string">'age'</span>: <span class="number">20</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037fab8c08d31574a6bd24'</span>), <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'Jordan'</span>, <span class="string">'age'</span>: <span class="number">20</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br></pre></td></tr></table></figure><p>如果要查询年龄大于20的数据,则写法如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 这里查询的条件键值已经不是单纯的数字了,而是一个字典,其键名为比较符号$gt,意思是大于,键值为20。</span></span><br><span class="line"><span class="meta">>>> </span>results = collection.find({<span class="string">'age'</span>: {<span class="string">'$gt'</span>: <span class="number">20</span>}})</span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> result <span class="keyword">in</span> results:</span><br><span class="line"><span class="meta">... </span> print(result)</span><br><span class="line">...</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037d818c08d31574a6bd22'</span>), <span class="string">'id'</span>: <span class="string">'20170202'</span>, <span class="string">'name'</span>: <span class="string">'Mike'</span>, <span class="string">'age'</span>: <span class="number">21</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037fab8c08d31574a6bd25'</span>), <span class="string">'id'</span>: <span class="string">'20170202'</span>, <span class="string">'name'</span>: <span class="string">'Mike'</span>, <span class="string">'age'</span>: <span class="number">21</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br></pre></td></tr></table></figure><p>这里将比较符号归纳为下表 :</p><p><img src="https://s1.ax1x.com/2018/05/22/C2LcxH.png" alt="比较符合归纳表"></p><p>还可以进行正则匹配查询。例如,查询名字以M开头的学生数据,示例如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 这里使用$regex来指定正则匹配,^M.*代表以M开头的正则表达式。</span></span><br><span class="line"><span class="meta">>>> </span>results = collection.find({<span class="string">'name'</span>: {<span class="string">'$regex'</span>: <span class="string">'^M.*'</span>}})</span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> result <span class="keyword">in</span> results:</span><br><span class="line"><span class="meta">... </span> print(result)</span><br><span class="line">...</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037d818c08d31574a6bd22'</span>), <span class="string">'id'</span>: <span class="string">'20170202'</span>, <span class="string">'name'</span>: <span class="string">'Mike'</span>, <span class="string">'age'</span>: <span class="number">21</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037fab8c08d31574a6bd25'</span>), <span class="string">'id'</span>: <span class="string">'20170202'</span>, <span class="string">'name'</span>: <span class="string">'Mike'</span>, <span class="string">'age'</span>: <span class="number">21</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br></pre></td></tr></table></figure><p>这里将一些功能符号再归类为下表 :</p><p><img src="https://s1.ax1x.com/2018/05/22/C2LjZq.png" alt="功能符号表"></p><h3 id="计数"><a href="#计数" class="headerlink" title="计数"></a>计数</h3><p>要统计查询结果有多少条数据,可以调用<code>count()</code>方法。比如,统计所有数据条数 :</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>count = collection.find().count()</span><br><span class="line"><span class="meta">>>> </span>print(count)</span><br><span class="line"><span class="number">6</span></span><br></pre></td></tr></table></figure><p>统计符合某个条件的数据:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>count = collection.find({<span class="string">'age'</span>: <span class="number">20</span>}).count()</span><br><span class="line"><span class="comment"># 运行结果是一个数值,即符合条件的数据条数。</span></span><br><span class="line"><span class="meta">>>> </span>print(count)</span><br><span class="line"><span class="number">4</span></span><br></pre></td></tr></table></figure><h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><p>排序时,直接调用<code>sort()</code>方法,并在其中传入排序的字段及升降序标志即可。示例如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>results = collection.find().sort(<span class="string">'name'</span>, pymongo.ASCENDING)</span><br><span class="line"><span class="meta">>>> </span>print([result[<span class="string">'name'</span>] <span class="keyword">for</span> result <span class="keyword">in</span> results])</span><br><span class="line">[<span class="string">'Jordan'</span>, <span class="string">'Jordan'</span>, <span class="string">'Jordan'</span>, <span class="string">'Jordan'</span>, <span class="string">'Mike'</span>, <span class="string">'Mike'</span>]</span><br></pre></td></tr></table></figure><p>这里我们调用<code>pymongo.ASCENDING</code>指定升序。如果要降序排列,可以传入<code>pymongo.DESCENDING</code>。</p><h3 id="偏移"><a href="#偏移" class="headerlink" title="偏移"></a>偏移</h3><p>在某些情况下,我们可能想只取某几个元素,这时可以利用<code>skip()</code>方法偏移几个位置,比如偏移2,就忽略前两个元素,得到第三个及以后的元素:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 忽略前两个</span></span><br><span class="line"><span class="meta">>>> </span>results = collection.find().sort(<span class="string">'name'</span>, pymongo.ASCENDING).skip(<span class="number">2</span>)</span><br><span class="line"><span class="meta">>>> </span>print([result[<span class="string">'name'</span>] <span class="keyword">for</span> result <span class="keyword">in</span> results])</span><br><span class="line">[<span class="string">'Jordan'</span>, <span class="string">'Jordan'</span>, <span class="string">'Mike'</span>, <span class="string">'Mike'</span>]</span><br></pre></td></tr></table></figure><p>另外,还可以用<code>limit()</code>方法指定要取的结果个数,示例如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>results = collection.find().sort(<span class="string">'name'</span>, pymongo.ASCENDING).skip(<span class="number">2</span>).limit(<span class="number">2</span>)</span><br><span class="line"><span class="meta">>>> </span>print([result[<span class="string">'name'</span>] <span class="keyword">for</span> result <span class="keyword">in</span> results])</span><br><span class="line">[<span class="string">'Jordan'</span>, <span class="string">'Jordan'</span>]</span><br></pre></td></tr></table></figure><h3 id="更新"><a href="#更新" class="headerlink" title="更新"></a>更新</h3><p>对于数据更新,我们可以使用<code>update()</code>方法,指定更新的条件和更新后的数据即可:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>condition = {<span class="string">'name'</span>: <span class="string">'Jordan'</span>}</span><br><span class="line"><span class="meta">>>> </span>student = collection.find_one(condition)</span><br><span class="line"><span class="meta">>>> </span>student</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037d008c08d31574a6bd20'</span>), <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'</span></span><br><span class="line"><span class="string">Jordan'</span>, <span class="string">'age'</span>: <span class="number">20</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line"><span class="meta">>>> </span>student[<span class="string">'age'</span>] = <span class="number">25</span></span><br><span class="line"><span class="meta">>>> </span>student</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037d008c08d31574a6bd20'</span>), <span class="string">'id'</span>: <span class="string">'20170101'</span>, <span class="string">'name'</span>: <span class="string">'</span></span><br><span class="line"><span class="string">Jordan'</span>, <span class="string">'age'</span>: <span class="number">25</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>result = collection.update(condition, student)</span><br><span class="line"><span class="comment"># 返回结果是字典形式,ok代表执行成功,nModified代表影响的数据条数。</span></span><br><span class="line"><span class="meta">>>> </span>result</span><br><span class="line">{<span class="string">'n'</span>: <span class="number">1</span>, <span class="string">'nModified'</span>: <span class="number">1</span>, <span class="string">'ok'</span>: <span class="number">1.0</span>, <span class="string">'updatedExisting'</span>: <span class="keyword">True</span>}</span><br></pre></td></tr></table></figure><p>这里我们要更新<code>name</code>为<code>Kevin</code>的数据的年龄:首先指定查询条件,然后将数据查询出来,修改年龄后调用<code>update()</code>方法将原条件和修改后的数据传入 。</p><p>另外,我们也可以使用<code>$set</code>操作符对数据进行更新,代码如下 :</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 这样只会更新字段,不会删除字段,这里即使stundent的数据被pop调用,也不会删除掉原数据。</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.update(condition, {<span class="string">'$set'</span>: student})</span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line">{<span class="string">'n'</span>: <span class="number">1</span>, <span class="string">'nModified'</span>: <span class="number">0</span>, <span class="string">'ok'</span>: <span class="number">1.0</span>, <span class="string">'updatedExisting'</span>: <span class="keyword">True</span>}</span><br></pre></td></tr></table></figure><p>这样可以只更新<code>student</code>字典内存在的字段。如果原先还有其他字段,则不会更新,也不会删除。而如果不用<code>$set</code>的话,则会把之前的数据全部用<code>student</code>字典替换;如果原本存在其他字段,则会被删除。</p><h4 id="update-one"><a href="#update-one" class="headerlink" title="update_one()"></a>update_one()</h4><p>另外,<code>update()</code>方法其实也是官方不推荐使用的方法。这里也分为<code>update_one()</code>方法和<code>update_many()</code>方法,用法更加严格,它们的第二个参数需要使用<code>$</code>类型操作符作为字典的键名 。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>condition = {<span class="string">'name'</span>: <span class="string">'Jordan'</span>}</span><br><span class="line"><span class="meta">>>> </span>student = collection.find_one(condition)</span><br><span class="line"><span class="meta">>>> </span>student</span><br><span class="line">{<span class="string">'_id'</span>: ObjectId(<span class="string">'5b037d008c08d31574a6bd20'</span>), <span class="string">'id'</span>: <span class="string">'20170102'</span>, <span class="string">'name'</span>: <span class="string">'Jordan'</span>, <span class="string">'age'</span>: <span class="number">25</span>, <span class="string">'gender'</span>: <span class="string">'male'</span>}</span><br><span class="line"><span class="meta">>>> </span>student[<span class="string">'age'</span>] = <span class="number">26</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.update_one(condition, {<span class="string">'$set'</span>: student})</span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line"><pymongo.results.UpdateResult object at <span class="number">0x0000000003AF8C60</span>></span><br><span class="line"><span class="meta">>>> </span>print(result.matched_count, result.modified_count)</span><br><span class="line"><span class="number">1</span> <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 这里调用了update_one()方法,第二个参数不能再直接传入修改后的字典,而是需要使用{'$set': student}这样的形式,其返回结果是UpdateResult类型。然后分别调用matched_count和modified_count属性,可以获得匹配的数据条数和影响的数据条数。</span></span><br></pre></td></tr></table></figure><p>我们再看一个例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查询条件年龄大于20岁</span></span><br><span class="line"><span class="meta">>>> </span>condition = {<span class="string">'age'</span>: {<span class="string">'$gt'</span>: <span class="number">20</span>}}</span><br><span class="line"><span class="comment"># 然后更新条件为{'$inc': {'age': 1}}, 年龄加1</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.update_one(condition, {<span class="string">'$inc'</span>: {<span class="string">'age'</span>: <span class="number">1</span>}})</span><br><span class="line"><span class="comment"># 执行之后会将第一条符合条件的数据年龄加1。</span></span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line"><pymongo.results.UpdateResult object at <span class="number">0x0000000003AF8EA0</span>></span><br><span class="line"><span class="meta">>>> </span>print(result.matched_count, result.modified_count)</span><br><span class="line"><span class="number">1</span> <span class="number">1</span></span><br></pre></td></tr></table></figure><h4 id="update-many"><a href="#update-many" class="headerlink" title="update_many()"></a>update_many()</h4><p>如果调用<code>update_many()</code>方法,则会将所有符合条件的数据都更新,示例如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>condition = {<span class="string">'age'</span>: {<span class="string">'$gt'</span>: <span class="number">20</span>}}</span><br><span class="line"><span class="comment"># 更新多条数据</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.update_many(condition, {<span class="string">'$inc'</span>: {<span class="string">'age'</span>: <span class="number">1</span>}})</span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line"><pymongo.results.UpdateResult object at <span class="number">0x0000000003AF8090</span>></span><br><span class="line"><span class="comment"># 可以看到,这时所有匹配到的数据都会被更新。</span></span><br><span class="line"><span class="meta">>>> </span>print(result.matched_count, result.modified_count)</span><br><span class="line"><span class="number">3</span> <span class="number">3</span></span><br></pre></td></tr></table></figure><h3 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h3><p>删除操作比较简单,直接调用<code>remove()</code>方法指定删除的条件即可,此时符合条件的所有数据均会被删除。示例如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>result = collection.remove({<span class="string">'name'</span>: <span class="string">'Mike'</span>})</span><br><span class="line"><span class="meta">>>> </span>print(result)</span><br><span class="line">{<span class="string">'n'</span>: <span class="number">2</span>, <span class="string">'ok'</span>: <span class="number">1.0</span>}</span><br></pre></td></tr></table></figure><h4 id="delete-one"><a href="#delete-one" class="headerlink" title="delete_one( )"></a>delete_one( )</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>result = collection.delete_one({<span class="string">'name'</span>: <span class="string">'Jordan'</span>})</span><br><span class="line"><span class="meta">>>> </span>result</span><br><span class="line"><pymongo.results.DeleteResult object at <span class="number">0x0000000003AF8BD0</span>></span><br><span class="line"><span class="meta">>>> </span>print(result.deleted_count)</span><br><span class="line"><span class="number">1</span></span><br><span class="line">>>></span><br></pre></td></tr></table></figure><h4 id="delete-many"><a href="#delete-many" class="headerlink" title="delete_many()"></a>delete_many()</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 删除年龄小于25岁的多条记录</span></span><br><span class="line"><span class="meta">>>> </span>result = collection.delete_many({<span class="string">'age'</span>: {<span class="string">'$lt'</span>: <span class="number">25</span>}})</span><br><span class="line"><span class="meta">>>> </span>print(result.deleted_count)</span><br><span class="line"><span class="number">3</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h3 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h3><p>MongoDB是由C++语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似JSON对象,它的字段值可以包含其他文档、数组及文档数组,非常灵活。 在开始之前,请确保已经安装好了MongoDB并启动了其服务,并且安装好了Python的PyMongo库。</p>
<ul>
<li>Python 3.6</li>
<li><a href="[win32/mongodb-win32-x86_64-2008plus-ssl-v3.4-latest.zip](http://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-v3.4-latest.zip">mongodb3.4</a> )</li>
<li>pymongo 3.4.0</li>
</ul>
<h3 id="连接MongDB"><a href="#连接MongDB" class="headerlink" title="连接MongDB"></a>连接MongDB</h3><p>连接MongoDB时,我们需要使用PyMongo库里面的<code>MongoClient</code>。一般来说,传入MongoDB的IP及端口即可,其中第一个参数为地址<code>host</code>,第二个参数为端口<code>port</code>(如果不给它传递参数,默认是27017) 。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">import</span> pymongo</span><br><span class="line"><span class="comment"># 创建MongoDB的连接对象</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>client = pymongo.MongoClient(host=<span class="string">'localhost'</span>, port=<span class="number">27017</span>)</span><br></pre></td></tr></table></figure>
<h3 id="指定数据库和集合"><a href="#指定数据库和集合" class="headerlink" title="指定数据库和集合"></a>指定数据库和集合</h3><p>MongoDB中可以建立多个数据库,接下来我们需要指定操作哪个数据库;MongoDB的每个数据库又包含许多集合(collection),它们类似于关系型数据库中的表。下一步需要指定要操作的集合,这里指定一个集合名称为students。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建或者指定数据库db</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>db = client[<span class="string">'test'</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>db = client.test <span class="comment"># 这种方式也可以指定数据库db</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建或者指定集合</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>collection = db[<span class="string">'students'</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>collection = db.students <span class="comment"># 这种方式也可以指定集合</span></span><br><span class="line"><span class="comment"># 这样我们便声明了一个Collection对象。</span></span><br></pre></td></tr></table></figure>
<h3 id="插入数据"><a href="#插入数据" class="headerlink" title="插入数据"></a>插入数据</h3><h4 id="插入单条数据"><a href="#插入单条数据" class="headerlink" title="插入单条数据"></a>插入单条数据</h4><p>直接调用<code>collection</code>的<code>insert()</code>方法即可插入数据</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 新建一条学生数据,这条数据以字典形式表示</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>student = &#123;</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'20170101'</span>,</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'Jordan'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">20</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment"># 往集合中插入数据</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>result = collection.insert(student)</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>print(result) <span class="comment"># 返回insert后的 _id</span></span><br><span class="line"><span class="number">5</span>b02a3868c08d32b90ff9954</span><br></pre></td></tr></table></figure>
<p>在MongoDB中,每条数据其实都有一个<code>_id</code>属性来唯一标识。如果没有显式指明该属性,MongoDB会自动产生一个<code>ObjectId</code>类型的<code>_id</code>属性。<code>insert()</code>方法会在执行后返回<code>_id</code>值。</p>
<h4 id="插入多条数据"><a href="#插入多条数据" class="headerlink" title="插入多条数据"></a>插入多条数据</h4><p>当然,我们也可以同时插入多条数据,只需要以列表形式传递即可 。</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>student1 = &#123;</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'20170101'</span>,</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'Jordan'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">20</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>student2 = &#123;</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'20170202'</span>,</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'Mike'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">21</span>,</span><br><span class="line"> <span class="string">'gender'</span>: <span class="string">'male'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>result = collection.insert([student1, student2])</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>print(result)</span><br><span class="line">[ObjectId(<span class="string">'5b037d818c08d31574a6bd21'</span>), ObjectId(<span class="string">'5b037d818c08d31574a6bd22'</span>)]</span><br></pre></td></tr></table></figure>
<p>实际上,在PyMongo 3.x版本中,官方已经不推荐使用<code>insert()</code>方法了。当然,继续使用也没有什么问题。官方推荐使用<code>insert_one()</code>和<code>insert_many()</code>方法来分别插入单条记录和多条记录 。</p>
</summary>
<category term="NoSQL" scheme="http://www.chenfanlinux.org/categories/NoSQL/"/>
<category term="MongDB" scheme="http://www.chenfanlinux.org/tags/MongDB/"/>
</entry>
<entry>
<title>如何提升你的记忆力</title>
<link href="http://www.chenfanlinux.org/2018/05/27/%E5%A6%82%E4%BD%95%E6%8F%90%E5%8D%87%E4%BD%A0%E7%9A%84%E8%AE%B0%E5%BF%86%E5%8A%9B/"/>
<id>http://www.chenfanlinux.org/2018/05/27/如何提升你的记忆力/</id>
<published>2018-05-27T05:36:57.000Z</published>
<updated>2018-05-27T05:45:11.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>刚放在手里的东西,转身就找不到了。明明话就在嘴边,但怎么都想不起来,别人一次就能记住的事情,你却要默背好多遍。别埋怨自己记性不好,其实记忆力也可以通过锻炼提高的。下面介绍这20个方法,挽救一下你的记忆力!</p></blockquote><h3 id="1-经常大笑"><a href="#1-经常大笑" class="headerlink" title="1. 经常大笑"></a>1. 经常大笑</h3><p>笑能保持大脑活力,让思维更明捷。定期与亲友聚会,给老友打个电话,晚餐后与家人聊天,都能让大脑感觉快乐。</p><h3 id="2-听不同类型的歌曲"><a href="#2-听不同类型的歌曲" class="headerlink" title="2. 听不同类型的歌曲"></a>2. 听不同类型的歌曲</h3><p>积极的接受不熟悉的音乐,听歌时除了关注旋律,还要认真琢磨歌词,这样不仅可以锻炼右脑,还会用到掌管语言的左脑。</p><h3 id="3-学习新技能"><a href="#3-学习新技能" class="headerlink" title="3. 学习新技能"></a>3. 学习新技能</h3><p>学习任何一项新技能都能促进大脑健康,例如学习新乐器、做手工、下棋等。</p><h3 id="4-多和他人交流"><a href="#4-多和他人交流" class="headerlink" title="4.多和他人交流"></a>4.多和他人交流</h3><p>与朋友交往,彼此分享经历、沟通情感、增加信任,思路变得更广,新想法也会更多,这些都是大脑的润滑剂。</p><h3 id="5-保证充足的睡眠"><a href="#5-保证充足的睡眠" class="headerlink" title="5.保证充足的睡眠"></a>5.保证充足的睡眠</h3><p>睡觉时,脑脊液在脑细胞间的循环比清醒时快很多,帮助大脑排出 “垃圾”,因为尽量避免熬夜,让大脑充分休息。</p><a id="more"></a><h3 id="6-给大脑出个难题"><a href="#6-给大脑出个难题" class="headerlink" title="6.给大脑出个难题"></a>6.给大脑出个难题</h3><p>“用进废退” 是大脑的使用原理,试着记忆路线、背一些电话号码、努力回忆想不起的事情,让大脑保持工作状态。</p><h3 id="7-大声朗读"><a href="#7-大声朗读" class="headerlink" title="7. 大声朗读"></a>7. 大声朗读</h3><p>朗读能把视觉的刺激反馈给听觉,还会用到唇、舌、喉等多个部位,这样带给大脑的刺激比默读大很多,记忆也更深刻。</p><h3 id="8-多回忆细节"><a href="#8-多回忆细节" class="headerlink" title="8. 多回忆细节"></a>8. 多回忆细节</h3><p>读书或者听讲时,要不时挺下来回想刚才读到或者听到的内容,越详细越好。大脑存储这些信息时,细节越多,以及效果越好。</p><h3 id="9-锻炼观察力"><a href="#9-锻炼观察力" class="headerlink" title="9. 锻炼观察力"></a>9. 锻炼观察力</h3><p>这是对抗健忘的最好方式之一,每次去一个新地方,在心中一下房间内物品的摆放位置,等离开时再试着回想,锻炼自己的观察力。</p><h3 id="10-将信息图像化"><a href="#10-将信息图像化" class="headerlink" title="10. 将信息图像化"></a>10. 将信息图像化</h3><p>运用视觉或者语言上的连续,可以帮助提升记忆。</p><h3 id="11-去陌生的地方散步"><a href="#11-去陌生的地方散步" class="headerlink" title="11. 去陌生的地方散步"></a>11. 去陌生的地方散步</h3><p>在不认识的地方散步时,右脑中会形成一幅地图。通过接触不了解的世界,可以使脑保持新鲜的状态。</p><h3 id="12-做个倾听者"><a href="#12-做个倾听者" class="headerlink" title="12.做个倾听者"></a>12.做个倾听者</h3><p>专心听别人说话,控制住自己插嘴发表意见的冲动。作为听众,不但能够增加信息输入,还可以对已有的信息进行整理。</p><h3 id="13-让大脑偶尔无聊一下"><a href="#13-让大脑偶尔无聊一下" class="headerlink" title="13. 让大脑偶尔无聊一下"></a>13. 让大脑偶尔无聊一下</h3><p>无聊的时候大脑的活动也会 “停滞” ,设定这样一个充电时期,让大脑进行充分的休息。你的记忆力就可能取得更大的飞跃。</p><h3 id="14-亲身体验是脑最宝贵的财富"><a href="#14-亲身体验是脑最宝贵的财富" class="headerlink" title="14. 亲身体验是脑最宝贵的财富"></a>14. 亲身体验是脑最宝贵的财富</h3><p>无论什么事,都要积极的投入。本来不感兴趣的事情,经过尝试后可能会获取意想不到的乐趣。好奇心是让大脑恢复年轻的第一步。</p><h3 id="15-吃早餐能活化大脑"><a href="#15-吃早餐能活化大脑" class="headerlink" title="15. 吃早餐能活化大脑"></a>15. 吃早餐能活化大脑</h3><p>研究表明,吃早餐的人群图像记忆,单词记忆能力更好。早餐中提取一天所需要的许多能量,会提高计算能力和创造力。</p><h3 id="16-多咀嚼可以提高记忆力"><a href="#16-多咀嚼可以提高记忆力" class="headerlink" title="16.多咀嚼可以提高记忆力"></a>16.多咀嚼可以提高记忆力</h3><p>研究显示,咀嚼时大脑感觉运动领域的血流量会增加25-28%,味觉中枢的血流量会增加9-17%。</p><h3 id="17-跳舞、游泳是最佳的运动"><a href="#17-跳舞、游泳是最佳的运动" class="headerlink" title="17.跳舞、游泳是最佳的运动"></a>17.跳舞、游泳是最佳的运动</h3><p>定期的锻炼可以促进负责记忆的脑细胞生长。游泳时大脑中的血液流量增加14%,而跳舞能让人们患认知障碍症的风险降低76%。</p><h3 id="18-小心盐伤大脑"><a href="#18-小心盐伤大脑" class="headerlink" title="18.小心盐伤大脑"></a>18.小心盐伤大脑</h3><p>高盐饮食加速认知能力退化。此外,咖啡因、味精、防腐剂、反式脂肪酸都是大脑的“杀手”。</p><h3 id="19-每天静心30分钟"><a href="#19-每天静心30分钟" class="headerlink" title="19. 每天静心30分钟"></a>19. 每天静心30分钟</h3><p>冥想能改善认知与心智作用,还能减缓衰老、缓解压力。每天30-60分钟静下心来冥想,是最好的“大脑澡”。</p><h3 id="20-勤动手指"><a href="#20-勤动手指" class="headerlink" title="20. 勤动手指"></a>20. 勤动手指</h3><p>学做针线活,练习绘画,或者用手握两个健身球,让健身球在手中旋转,长期坚持都会有健脑作用。</p>]]></content>
<summary type="html">
<blockquote>
<p>刚放在手里的东西,转身就找不到了。明明话就在嘴边,但怎么都想不起来,别人一次就能记住的事情,你却要默背好多遍。别埋怨自己记性不好,其实记忆力也可以通过锻炼提高的。下面介绍这20个方法,挽救一下你的记忆力!</p>
</blockquote>
<h3 id="1-经常大笑"><a href="#1-经常大笑" class="headerlink" title="1. 经常大笑"></a>1. 经常大笑</h3><p>笑能保持大脑活力,让思维更明捷。定期与亲友聚会,给老友打个电话,晚餐后与家人聊天,都能让大脑感觉快乐。</p>
<h3 id="2-听不同类型的歌曲"><a href="#2-听不同类型的歌曲" class="headerlink" title="2. 听不同类型的歌曲"></a>2. 听不同类型的歌曲</h3><p>积极的接受不熟悉的音乐,听歌时除了关注旋律,还要认真琢磨歌词,这样不仅可以锻炼右脑,还会用到掌管语言的左脑。</p>
<h3 id="3-学习新技能"><a href="#3-学习新技能" class="headerlink" title="3. 学习新技能"></a>3. 学习新技能</h3><p>学习任何一项新技能都能促进大脑健康,例如学习新乐器、做手工、下棋等。</p>
<h3 id="4-多和他人交流"><a href="#4-多和他人交流" class="headerlink" title="4.多和他人交流"></a>4.多和他人交流</h3><p>与朋友交往,彼此分享经历、沟通情感、增加信任,思路变得更广,新想法也会更多,这些都是大脑的润滑剂。</p>
<h3 id="5-保证充足的睡眠"><a href="#5-保证充足的睡眠" class="headerlink" title="5.保证充足的睡眠"></a>5.保证充足的睡眠</h3><p>睡觉时,脑脊液在脑细胞间的循环比清醒时快很多,帮助大脑排出 “垃圾”,因为尽量避免熬夜,让大脑充分休息。</p>
</summary>
<category term="生活技巧" scheme="http://www.chenfanlinux.org/categories/%E7%94%9F%E6%B4%BB%E6%8A%80%E5%B7%A7/"/>
<category term="记忆力" scheme="http://www.chenfanlinux.org/tags/%E8%AE%B0%E5%BF%86%E5%8A%9B/"/>
</entry>
<entry>
<title>Python数据分析之Pandas入门修订版(四)</title>
<link href="http://www.chenfanlinux.org/2018/05/01/Python%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E4%B9%8BPandas%E5%85%A5%E9%97%A8%E4%BF%AE%E8%AE%A2%E7%89%88-%E5%9B%9B/"/>
<id>http://www.chenfanlinux.org/2018/05/01/Python数据分析之Pandas入门修订版-四/</id>
<published>2018-05-01T12:32:42.000Z</published>
<updated>2018-05-01T12:34:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="Pandas的数据结构"><a href="#Pandas的数据结构" class="headerlink" title="Pandas的数据结构"></a>Pandas的数据结构</h2><blockquote><p>Pandas 的数据结构:Pandas 主要有 Series(一维数组),DataFrame(二维数组),Panel(三维数组),Panel4D(四维数组),PanelND(更多维数组)等数据结构。其中 Series 和 DataFrame 应用的最为广泛。</p></blockquote><h3 id="Series"><a href="#Series" class="headerlink" title="Series"></a>Series</h3><p>Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据索引组成。仅由一组数据即可产生最简单的Series。 Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射,这种数据结构相对于数组来说,使用起来更加的灵活。</p><p><img src="https://s1.ax1x.com/2018/04/28/C8mNSx.png" alt="Series"></p><h4 id="通过list构建Series"><a href="#通过list构建Series" class="headerlink" title="通过list构建Series"></a>通过list构建Series</h4><pre><code>>>> import numpy as np>>> import pandas as pd>>> from pandas import Series,DataFrame>>> s1= Series(range(10, 20))>>> print(type(s1)) <class 'pandas.core.series.Series'></code></pre><p>由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。</p><a id="more"></a><h4 id="指定Series的索引"><a href="#指定Series的索引" class="headerlink" title="指定Series的索引"></a>指定Series的索引</h4><p>我们希望所创建的Series带有一个可以对各个数据点进行标记的索引,<br>创建 Series 语法: <code>s = pd.Series(data, index=index)</code></p><pre><code>>>> s2 = Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])>>> s2d 4b 7a -5c 3dtype: int64>>> # 通过字典的方式创建Series,就可以指定Series的索引,键值即为索引。>>> sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}>>> s3 = Series(sdata)>>> s3Ohio 35000Oregon 16000Texas 71000Utah 5000dtype: int64</code></pre><h4 id="获取Series-index及value信息"><a href="#获取Series-index及value信息" class="headerlink" title="获取Series index及value信息"></a>获取Series index及value信息</h4><pre><code>>>> s1.valuesarray([10, 11, 12, 13, 14, 15, 16, 17, 18, 19], dtype=int64)>>>>>>>>> s1.index # 这里的索引也是一种不可变的数据类型RangeIndex(start=0, stop=10, step=1)</code></pre><h4 id="Series-的简单运算"><a href="#Series-的简单运算" class="headerlink" title="Series 的简单运算"></a>Series 的简单运算</h4><p>如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接,索引与数据的对应关系仍保持在数组运算的结果中。</p><pre><code>>>> s1[s1>10] # 布尔型数组进行过滤1 112 123 134 145 156 167 178 189 19>>> s1 * 2 # 标量乘法0 201 222 243 264 285 306 327 348 369 38>>> np.exp(s2) # 应用数学函数d 54.598150b 1096.633158a 0.006738c 20.085537</code></pre><h4 id="用于检测缺失数据"><a href="#用于检测缺失数据" class="headerlink" title="用于检测缺失数据"></a>用于检测缺失数据</h4><pre><code>>>> states = ['California', 'Ohio', 'Oregon', 'Texas'] # 自定义索引>>> sdata{'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}>>> s4 = Series(sdata,index=states) # 自定义的索引,如果找不到数据,则用np.nan填充>>> s4California NaNOhio 35000.0Oregon 16000.0Texas 71000.0>>> s4.isnull() # any(s4.isnull()),判断是否存在空值,为True则存在空值California TrueOhio FalseOregon FalseTexas Falsedtype: bool>>> s4.notnull() # all(s4.notnull()),判断是否不存在空值,为True则不存在空值California FalseOhio TrueOregon TrueTexas True</code></pre><h4 id="根据运算的索引标签自动对齐数据"><a href="#根据运算的索引标签自动对齐数据" class="headerlink" title="根据运算的索引标签自动对齐数据"></a>根据运算的索引标签自动对齐数据</h4><pre><code>>>> s3Ohio 35000Oregon 16000Texas 71000Utah 5000dtype: int64>>> s4California NaNOhio 35000.0Oregon 16000.0Texas 71000.0dtype: float64>>> s3 + s4California NaNOhio 70000.0Oregon 32000.0Texas 142000.0Utah NaN</code></pre><h4 id="Series对象本身及其索引都有一个name属性"><a href="#Series对象本身及其索引都有一个name属性" class="headerlink" title="Series对象本身及其索引都有一个name属性"></a>Series对象本身及其索引都有一个name属性</h4><pre><code>>>> s4.name = 'population'>>> s4.index.name = 'state'>>> s4stateCalifornia NaNOhio 35000.0Oregon 16000.0Texas 71000.0Name: population, dtype: float64</code></pre><h3 id="DataFrame"><a href="#DataFrame" class="headerlink" title="DataFrame"></a>DataFrame</h3><p>DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。</p><p><img src="https://s1.ax1x.com/2018/04/28/C81029.png" alt="DataFrame"></p><h4 id="通过ndarray构建DataFrame"><a href="#通过ndarray构建DataFrame" class="headerlink" title="通过ndarray构建DataFrame"></a>通过ndarray构建DataFrame</h4><pre><code>>>> array = np.random.randn(5,4) # 创建一个二维随机数组>>> arrayarray([[ 0.65841573, -1.07248869, 0.30964663, 1.21059912], [-1.86075076, -0.54301326, -0.86993544, 0.1258058 ], [-1.44156445, -1.26253688, 1.31982877, 0.07189273], [ 0.65928548, 0.22667447, 0.57582044, 0.05462809], [-0.47716718, 0.08947818, -0.91467834, 2.59116919]])>>> df1 = DataFrame(array) # 通过ndarray构建DataFrame>>> df1 0 1 2 30 0.658416 -1.072489 0.309647 1.2105991 -1.860751 -0.543013 -0.869935 0.1258062 -1.441564 -1.262537 1.319829 0.0718933 0.659285 0.226674 0.575820 0.0546284 -0.477167 0.089478 -0.914678 2.591169</code></pre><h4 id="通过字典嵌套列表方式创建DataFrame"><a href="#通过字典嵌套列表方式创建DataFrame" class="headerlink" title="通过字典嵌套列表方式创建DataFrame"></a>通过字典嵌套列表方式创建DataFrame</h4><pre><code>data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2001, 2002, 2003], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}>>> df2 = DataFrame(data)>>> df2 pop state year0 1.5 Ohio 20001 1.7 Ohio 20012 3.6 Ohio 20023 2.4 Nevada 20014 2.9 Nevada 20025 3.2 Nevada 2003>>> data1 # 数据某一列只填充一个值,这时会发生广播,补全。{'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2], 'year': 2000, 'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada']}>>> DataFrame(data1) pop state year0 1.5 Ohio 20001 1.7 Ohio 20002 3.6 Ohio 20003 2.4 Nevada 20004 2.9 Nevada 20005 3.2 Nevada 2000</code></pre><h4 id="通过嵌套的字典创建DataFrame"><a href="#通过嵌套的字典创建DataFrame" class="headerlink" title="通过嵌套的字典创建DataFrame"></a>通过嵌套的字典创建DataFrame</h4><pre><code>>>> pop = {'Nevada': {2001: 2.4, 2002: 2.9},'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}>>> df3 = DataFrame(pop)>>> df3 Nevada Ohio2000 NaN 1.52001 2.4 1.72002 2.9 3.6</code></pre><p><strong><em>注意:这里外层字典的键作为列,内层键则作为行索引</em></strong></p><h4 id="设置DataFrame的index和columns的name属性"><a href="#设置DataFrame的index和columns的name属性" class="headerlink" title="设置DataFrame的index和columns的name属性"></a>设置DataFrame的index和columns的name属性</h4><pre><code>>>> df3.index.name ='year';df3.columns.name ='state'>>> df3state Nevada Ohioyear2000 NaN 1.52001 2.4 1.72002 2.9 3.6</code></pre><h4 id="获取DataFrame的index-columns及values信息"><a href="#获取DataFrame的index-columns及values信息" class="headerlink" title="获取DataFrame的index,columns及values信息"></a>获取DataFrame的index,columns及values信息</h4><pre><code>>>> df3.index # 不可变数据类型Int64Index([2000, 2001, 2002], dtype='int64', name='year')>>> df3.index[0] = 2017>>> df3.columns # 不可变数据类型Index(['Nevada', 'Ohio'], dtype='object', name='state')>>> df3.valuesarray([[nan, 1.5], [2.4, 1.7], [2.9, 3.6]])</code></pre><h3 id="索引对象"><a href="#索引对象" class="headerlink" title="索引对象"></a>索引对象</h3><p>pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index。Series和DataFrame中的索引都是index对象。</p><ul><li>Index 普通索引</li><li>Int64Index 整形索引</li><li>MultiIndex 层级索引 </li><li>DatetimeIndex 时间戳索引</li></ul><p>理解索引对象的原理很重要。</p><pre><code>>>> obj = pd.Series(range(3), index=['a', 'b', 'c'])>>> index = obj.index>>> index[1:]Index(['b', 'c'], dtype='object')</code></pre><p>index对象是不可变的,因此用户不能对其进行修改</p><pre><code>>>> index[1] = 'd' Traceback (most recent call last): File "<stdin>", line 1, in <module> File "F:\Python35\lib\site-packages\pandas\core\indexes\base.py", line 1724, in __setitem__ raise TypeError("Index does not support mutable operations")TypeError: Index does not support mutable operations</code></pre><p>不可变可以使Index对象在多个数据结构之间安全共享,防止被修改</p><pre><code>>>> labels = pd.Index(np.arange(3))>>> labelsInt64Index([0, 1, 2], dtype='int64')>>> obj2 = Series([1.5,2.5,0],index=labels)>>> obj20 1.51 2.52 0.0>>> obj2.index is labelsTrue</code></pre><p>与python的集合不同,pandas的Index可以包含重复的标签:</p><pre><code>>>> dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])>>> dup_labelsIndex(['foo', 'foo', 'bar', 'bar'], dtype='object')>>> obj3 = Series([1,2,3,4],index=dup_labels)>>> obj3['bar']bar 3bar 4</code></pre><h2 id="数据操作"><a href="#数据操作" class="headerlink" title="数据操作"></a>数据操作</h2><h3 id="索引操作"><a href="#索引操作" class="headerlink" title="索引操作"></a>索引操作</h3><h4 id="Series索引"><a href="#Series索引" class="headerlink" title="Series索引"></a>Series索引</h4><ul><li>行索引 s1[‘label’],s1[pos]</li><li>切片索引 s1[‘lab1’:’lab3’],s1[pos1:pos2] 按索引名切片是,是包括终止索引的</li><li>不连续索引 s1[[‘lab1,lab3,lab4’]],s1[[pos1,pos3]]</li><li>布尔索引</li></ul><p>example:</p><pre><code>>>> s1 = Series(np.arange(5),index=['a','b','c','d','e'])>>> s1a 0b 1c 2d 3e 4dtype: int32>>> # 1. 行索引>>> s1[0] # 通过索引位置0>>>>>> s1['a'] # 通过索引名label0>>> >>> # 2. 切片索引>>> s1[0:3] # 通过位置切片a 0b 1c 2>>> s1['a':'c'] # 通过索引名切片,不包括终止索引a 0b 1c 2>>> # 3. 不连续索引>>> s1[[0,3]] # 通过位置不连续索引a 0d 3>>> s1[['a','d']] # 通过索引名不连续索引a 0d 3>>> # 4. 布尔型索引>>> s1[s1>2] # 布尔型数组d 3e 4</code></pre><h4 id="DataFrame索引"><a href="#DataFrame索引" class="headerlink" title="DataFrame索引"></a>DataFrame索引</h4><p>DataFrame默认对列先进行操作,用一个值或序列对DataFrame进行索引其实就是获取一个或多个列。在一开始设计pandas时,我觉得用frame[:, col]选取列过于繁琐(也容易出错),因为列的选择是非常常见的操作。</p><ul><li>列索引 df[‘lab1’]</li><li>不连续列索引 df[[‘lab1’,’lab2’]]</li></ul><p>example:</p><pre><code>>>> df1 = DataFrame(np.arange(16).reshape((4, 4)),index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'])>>> df1 one two three fourOhio 0 1 2 3Colorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15>>> df1['two'] # 访问一列 Ohio 1Colorado 5Utah 9New York 13Name: two, dtype: int32>>> df1[['three','one']] # 访问多列 three oneOhio 2 0Colorado 6 4Utah 10 8New York 14 12</code></pre><p>这种索引方式有几个特殊的情况。首先通过切片或布尔型数组选取数据</p><pre><code>>>> df1[:2] # 切片 one two three fourOhio 0 1 2 3Colorado 4 5 6 7>>> df1[data['three'] > 5] # 布尔型数组 one two three fourColorado 4 5 6 7Utah 8 9 10 11New York 12 13 14 15</code></pre><h4 id="使用iloc和loc"><a href="#使用iloc和loc" class="headerlink" title="使用iloc和loc"></a>使用iloc和loc</h4><p>对于DataFrame的行的标签索引,我引入了特殊的标签运算符loc和iloc。它们可以让你用类似NumPy的标记,使用轴标签(loc)或整数索引(iloc),从DataFrame选择行和列的子集。</p><ul><li>.loc(标签索引)</li><li>.iloc(位置索引)</li><li>.ix(混合索引) 标签和位置混合索引,先按标签索引尝试操作,再按位置索引操作</li></ul><p>注意: </p><ul><li>DataFrame索引时,可以将其看作成ndarray</li><li>标签索引的索引时包含末尾位置的</li></ul><p>example:</p><pre><code>>>> s1 = pd.Series(range(5), index = ['a', 'b', 'c', 'd', 'e'])>>>>>> df1= pd.DataFrame(np.random.randn(5,4), columns = ['a', 'b', 'c', 'd'])>>> s1a 0b 1c 2d 3e 4dtype: int64>>> df1 a b c d0 -2.014533 -0.397137 1.437047 -0.2124871 -2.163297 -0.345989 -0.629438 -1.1099842 -1.710392 -0.676153 1.026213 -1.3691193 0.703873 -0.368941 -0.279216 -1.4148994 -1.685372 1.783007 -0.182695 -0.059630</code></pre><p><strong>1. 标签索引 loc</strong></p><pre><code>>>> # Series>>> s1['b':'d']b 1c 2d 3dtype: int64>>> s1.loc['b':'d']b 1c 2d 3>>> # DataFrame>>> df1['a']0 -2.0145331 -2.1632972 -1.7103923 0.7038734 -1.685372Name: a, dtype: float64>>> df1.loc[0:2,'a']0 -2.0145331 -2.1632972 -1.710392</code></pre><p><strong>2. 整型位置索引 iloc</strong> </p><pre><code>>>> # Series>>> s1[1:3]b 1c 2dtype: int64>>> s1.iloc[1:3]b 1c 2>>> # DataFrame>>> df1.iloc[0:2,0] # 注意与 df1.loc[0:2,'a']的区别0 -2.0145331 -2.163297</code></pre><p><strong>3. 混合索引 ix</strong> </p><p>当不清楚索引方式的时候,可以采用混合索引。</p><pre><code>>>> # Series>>> s1.ix[1:3]b 1c 2dtype: int64>>> s1.ix['b':'c']b 1c 2>>> # DataFrame>>> df1.ix[0:2,0] # # 先按标签索引尝试操作,然后再按位置索引尝试操作0 -2.0145331 -2.1632972 -1.710392</code></pre><p><img src="https://s1.ax1x.com/2018/05/01/CJdNmF.png" alt=""></p><h3 id="对齐运算与填充值"><a href="#对齐运算与填充值" class="headerlink" title="对齐运算与填充值"></a>对齐运算与填充值</h3><h4 id="对齐运算"><a href="#对齐运算" class="headerlink" title="对齐运算"></a>对齐运算</h4><p>按索引对齐运算,对齐操作在不重叠的索引处引入了NA值</p><pre><code>>>> s1 = pd.Series(range(10, 20), index = range(10))>>> s2 = pd.Series(range(20, 25), index = range(5))>>> s10 101 112 123 134 145 156 167 178 189 19>>> s20 201 212 223 234 24>>> # Series 对齐运算>>> s1 + s20 30.01 32.02 34.03 36.04 38.05 NaN6 NaN7 NaN8 NaN9 NaN</code></pre><p>对于DataFrame,对齐操作会同时发生在行和列上,如果DataFrame对象相加,没有共用的列或行标签,结果都会是空。</p><pre><code>>>> # Pandas 对齐运算>>> df1 = pd.DataFrame(np.ones((2,2)), columns = ['a', 'b'])>>> df2 = pd.DataFrame(np.ones((3,3)), columns = ['a', 'b', 'c']) >>> df1 a b0 1.0 1.01 1.0 1.0>>> df2 a b c0 1.0 1.0 1.01 1.0 1.0 1.02 1.0 1.0 1.0>>> df1 + df2 a b c0 2.0 2.0 NaN1 2.0 2.0 NaN2 NaN NaN NaN</code></pre><h4 id="填充值"><a href="#填充值" class="headerlink" title="填充值"></a>填充值</h4><pre><code>>>> s1.add(s2,fill_value=0) # fill_value=0会用原来的s1的数据去填充0 30.01 32.02 34.03 36.04 38.05 15.06 16.07 17.08 18.09 19.0>>> s3 = s1 + s2>>> s30 30.01 32.02 34.03 36.04 38.05 NaN6 NaN7 NaN8 NaN9 NaN>>> s3.fillna(-1) # 全部都填充一个值0 30.01 32.02 34.03 36.04 38.05 -1.06 -1.07 -1.08 -1.09 -1.0</code></pre><h3 id="函数应用和映射"><a href="#函数应用和映射" class="headerlink" title="函数应用和映射"></a>函数应用和映射</h3><ul><li>NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象</li><li>通过apply将函数应用到行或列上,注意轴方向,默认axis=0</li><li>通applymap将函数应用到每个数据上</li></ul><h4 id="Numpy-ufuncs-函数"><a href="#Numpy-ufuncs-函数" class="headerlink" title="Numpy ufuncs 函数"></a>Numpy ufuncs 函数</h4><pre><code>>>> df = pd.DataFrame(np.random.randn(5,4) - 1)>>> df 0 1 2 30 -2.345628 0.099349 -1.081593 -0.4365341 -1.825629 -0.603085 -0.151743 -0.6573112 0.010755 -0.761262 -1.859229 -0.4685873 -0.464764 -1.316331 -1.531675 -0.9990454 -1.283275 -1.631468 -2.359166 0.175304>>> np.abs(df) 0 1 2 30 2.345628 0.099349 1.081593 0.4365341 1.825629 0.603085 0.151743 0.6573112 0.010755 0.761262 1.859229 0.4685873 0.464764 1.316331 1.531675 0.9990454 1.283275 1.631468 2.359166 0.175304</code></pre><h4 id="使用apply应用行或列数据"><a href="#使用apply应用行或列数据" class="headerlink" title="使用apply应用行或列数据"></a>使用apply应用行或列数据</h4><pre><code>>>> f = lambda x:x.max() # x为一行或者一列数据>>> df 0 1 2 30 -2.345628 0.099349 -1.081593 -0.4365341 -1.825629 -0.603085 -0.151743 -0.6573112 0.010755 -0.761262 -1.859229 -0.4685873 -0.464764 -1.316331 -1.531675 -0.9990454 -1.283275 -1.631468 -2.359166 0.175304>>> df.apply(f)0 0.0107551 0.0993492 -0.1517433 0.175304>>> df.apply(f,axis=0) # 默认axis=0,每一列的最大值0 0.0107551 0.0993492 -0.1517433 0.175304dtype: float64>>> df.apply(f,axis=1) # 每一行的最大值0 0.0993491 -0.1517432 0.0107553 -0.4647644 0.175304</code></pre><h4 id="使用applymap应用到每个数据"><a href="#使用applymap应用到每个数据" class="headerlink" title="使用applymap应用到每个数据"></a>使用applymap应用到每个数据</h4><pre><code>>>> f2 = lambda x : '%.2f' % x>>> df.applymap(f2) 0 1 2 30 -2.35 0.10 -1.08 -0.441 -1.83 -0.60 -0.15 -0.662 0.01 -0.76 -1.86 -0.473 -0.46 -1.32 -1.53 -1.004 -1.28 -1.63 -2.36 0.18</code></pre><p>之所以叫做applymap,是因为Series有一个用于应用元素级函数的map方法</p><pre><code>>>> df[2].map(f2)0 -1.081 -0.152 -1.863 -1.534 -2.36</code></pre><h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><p>根据条件对数据集排序(sorting)也是一种重要的内置运算。要对行或列索引进行排序(按字典顺序),可使用sort_index方法,它将返回一个已排序的新对象。</p><h4 id="sort-index"><a href="#sort-index" class="headerlink" title="sort_index"></a>sort_index</h4><pre><code>>>> s1 = pd.Series(range(4), index=['d', 'a', 'b', 'c'])>>> s1d 0a 1b 2c 3dtype: int64>>> s1.sort_index()a 1b 2c 3d 0</code></pre><p>对于DataFrame,则可以根据任意一个轴上的索引进行排序</p><pre><code>>>> df = pd.DataFrame(np.arange(8).reshape((2, 4)),index=['three', 'one'], columns=['d', 'a', 'b', 'c'])>>> df d a b cthree 0 1 2 3one 4 5 6 7>>> df.sort_index() # axis=0 d a b cone 4 5 6 7three 0 1 2 3>>> df.sort_index(axis=1) a b c dthree 1 2 3 0one 5 6 7 4</code></pre><p>数据默认是按升序排序的,但也可以降序排序:</p><pre><code>>>> df.sort_index(axis=1, ascending=False)</code></pre><h4 id="sort-values"><a href="#sort-values" class="headerlink" title="sort_values"></a>sort_values</h4><p>若要按值对Series进行排序,可使用其sort_values方法:</p><pre><code>>>> s1.sort_values()d 0a 1b 2c 3</code></pre><p>当排序一个DataFrame时,你可能希望根据一个或多个列中的值进行排序。将一个或多个列的名字传递给sort_values的by选项即可达到该目的:</p><pre><code>>>> df1.sort_values(by=['a']) a b0 0 42 0 -31 1 73 1 2>>> df1.sort_values(by=['a','b']) a b2 0 -30 0 43 1 21 1 7</code></pre><h3 id="统计计算与描述"><a href="#统计计算与描述" class="headerlink" title="统计计算与描述"></a>统计计算与描述</h3><h4 id="统计计算"><a href="#统计计算" class="headerlink" title="统计计算"></a>统计计算</h4><ul><li>sum, mean, max, min…</li><li>axis=0 按列统计, axis=1按行统计</li><li>skipna 排除缺失值, 默认为True</li><li>idmax, idmin, cumsum</li></ul><p>example:</p><pre><code>>>> df1 = DataFrame(np.random.randn(5,4),columns=['a', 'b','c', 'd'])>>> df1 a b c d0 0.053924 -0.322160 -1.534288 1.2490841 0.393977 -0.861401 0.195511 -0.6968182 1.859970 -0.907963 -1.615231 -1.6223803 -0.160392 0.381193 0.188679 0.4225874 -0.114821 -0.814193 -1.017537 1.439799>>> df1.sum() # 默认按axis=0,列进行统计a 2.032658b -2.524524c -3.782867d 0.792273dtype: float64>>> df1.max()a 1.859970b 0.381193c 0.195511d 1.439799dtype: float64>>> df1.min(axis=1)0 -1.5342881 -0.8614012 -1.6223803 -0.1603924 -1.017537</code></pre><h4 id="统计描述"><a href="#统计描述" class="headerlink" title="统计描述"></a>统计描述</h4><p>describe产生多个统计数据</p><pre><code>>>> df1.describe() a b c dcount 5.000000 5.000000 5.000000 5.000000mean 0.406532 -0.504905 -0.756573 0.158455std 0.841158 0.548582 0.895852 1.304219min -0.160392 -0.907963 -1.615231 -1.62238025% -0.114821 -0.861401 -1.534288 -0.69681850% 0.053924 -0.814193 -1.017537 0.42258775% 0.393977 -0.322160 0.188679 1.249084max 1.859970 0.381193 0.195511 1.439799</code></pre><p><img src="https://s1.ax1x.com/2018/05/01/CJcgn1.md.png" alt="describe"></p>]]></content>
<summary type="html">
<h2 id="Pandas的数据结构"><a href="#Pandas的数据结构" class="headerlink" title="Pandas的数据结构"></a>Pandas的数据结构</h2><blockquote>
<p>Pandas 的数据结构:Pandas 主要有 Series(一维数组),DataFrame(二维数组),Panel(三维数组),Panel4D(四维数组),PanelND(更多维数组)等数据结构。其中 Series 和 DataFrame 应用的最为广泛。</p>
</blockquote>
<h3 id="Series"><a href="#Series" class="headerlink" title="Series"></a>Series</h3><p>Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据索引组成。仅由一组数据即可产生最简单的Series。 Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射,这种数据结构相对于数组来说,使用起来更加的灵活。</p>
<p><img src="https://s1.ax1x.com/2018/04/28/C8mNSx.png" alt="Series"></p>
<h4 id="通过list构建Series"><a href="#通过list构建Series" class="headerlink" title="通过list构建Series"></a>通过list构建Series</h4><pre><code>&gt;&gt;&gt; import numpy as np
&gt;&gt;&gt; import pandas as pd
&gt;&gt;&gt; from pandas import Series,DataFrame
&gt;&gt;&gt; s1= Series(range(10, 20))
&gt;&gt;&gt; print(type(s1))
&lt;class &apos;pandas.core.series.Series&apos;&gt;
</code></pre><p>由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。</p>
</summary>
<category term="python数据分析" scheme="http://www.chenfanlinux.org/categories/python%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/"/>
<category term="Pandas" scheme="http://www.chenfanlinux.org/tags/Pandas/"/>
</entry>
<entry>
<title>Python数据分析之Pandas入门(三)</title>
<link href="http://www.chenfanlinux.org/2018/04/26/Python%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E4%B9%8BPandas%E5%85%A5%E9%97%A8-%E4%B8%89/"/>
<id>http://www.chenfanlinux.org/2018/04/26/Python数据分析之Pandas入门-三/</id>
<published>2018-04-26T07:35:44.000Z</published>
<updated>2018-04-26T07:38:33.000Z</updated>
<content type="html"><![CDATA[<blockquote><p>Pandas 是基于 NumPy 的一种数据处理工具,该工具为了解决数据分析任务而创建。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的函数和方法。</p></blockquote><h2 id="Pandas的常用数据结构"><a href="#Pandas的常用数据结构" class="headerlink" title="Pandas的常用数据结构"></a>Pandas的常用数据结构</h2><p>Pandas 的数据结构:Pandas 主要有 Series(一维数组),DataFrame(二维数组),Panel(三维数组),Panel4D(四维数组),PanelND(更多维数组)等数据结构。其中 Series 和 DataFrame 应用的最为广泛。</p><ul><li>Series 是一维带标签的数组,它可以包含任何数据类型。包括整数,字符串,浮点数,Python 对象等。Series 可以通过标签来定位。</li><li>DataFrame 是二维的带标签的数据结构。我们可以通过标签来定位数据。这是 NumPy 所没有的。</li></ul><h2 id="Series"><a href="#Series" class="headerlink" title="Series"></a>Series</h2><blockquote><p>Pandas 中,Series 可以被看作由 1 列数据组成的数据集。</p></blockquote><h3 id="创建-Series数据类型"><a href="#创建-Series数据类型" class="headerlink" title="创建 Series数据类型"></a>创建 Series数据类型</h3><p>创建 Series 语法: <code>s = pd.Series(data, index=index)</code>,可以通过多种方式进行创建, 这里的data的数据类型只要是序列都可以。</p><a id="more"></a><h4 id="从列表创建-Series"><a href="#从列表创建-Series" class="headerlink" title="从列表创建 Series"></a>从列表创建 Series</h4><pre><code>>>> import pandas as pd>>> arr = [0, 1, 2, 3, 4]>>> s1 = pd.Series(arr) # 如果不指定索引,则默认从 0 开始>>> s10 01 12 23 34 4dtype: int64</code></pre><p>注意:前面的 0,1,2,3,4 为当前 Series 的索引,后面的 0,1,2,3,4 为 Series 的值。</p><h4 id="从-Ndarray-创建-Series"><a href="#从-Ndarray-创建-Series" class="headerlink" title="从 Ndarray 创建 Series"></a>从 Ndarray 创建 Series</h4><pre><code>>>> import numpy as np>>> n = np.random.randn(5)>>> narray([ 0.39925835, 1.65144475, -0.72621788, 0.180224 , -0.99682087])>>> index = ['a', 'b', 'c', 'd', 'e']>>> s2 = pd.Series(n,index=index)>>> s2a 0.399258b 1.651445c -0.726218d 0.180224e -0.996821</code></pre><h4 id="从字典创建-Series"><a href="#从字典创建-Series" class="headerlink" title="从字典创建 Series"></a>从字典创建 Series</h4><pre><code>>>> d = {'a':1,'b':2,'c':3,'d':4,'e':5}>>> s3 = pd.Series(d)>>> s3a 1b 2c 3d 4e 5</code></pre><h3 id="Series-基本操作"><a href="#Series-基本操作" class="headerlink" title="Series 基本操作"></a>Series 基本操作</h3><h4 id="修改-Series-索引"><a href="#修改-Series-索引" class="headerlink" title="修改 Series 索引"></a>修改 Series 索引</h4><pre><code>>>> print(s1) # 以s1为例0 01 12 23 34 4>>> s1.index = ['A','B', 'C', 'D', 'E'] # 修改后的索引>>> s1A 0B 1C 2D 3E 4</code></pre><h4 id="Series-修改指定索引元素"><a href="#Series-修改指定索引元素" class="headerlink" title="Series 修改指定索引元素"></a>Series 修改指定索引元素</h4><pre><code>>>> s1A 0B 1C 2D 3E 4dtype: int64>>>>>>>>>>>> s1['A'] = 5>>> s1A 5B 1C 2D 3E 4</code></pre><h4 id="Series-按指定索引删除元素"><a href="#Series-按指定索引删除元素" class="headerlink" title="Series 按指定索引删除元素"></a>Series 按指定索引删除元素</h4><pre><code>>>> s1 = s1.drop('A')B 1C 2D 3E 4>>> s1B 1C 2D 3E 4</code></pre><h4 id="Series-纵向拼接"><a href="#Series-纵向拼接" class="headerlink" title="Series 纵向拼接"></a>Series 纵向拼接</h4><pre><code>>>> s4 = s3.append(s1)>>> s4a 1b 2c 3d 4e 5B 1C 2D 3E 4</code></pre><h4 id="Series-按指定索引查找元素"><a href="#Series-按指定索引查找元素" class="headerlink" title="Series 按指定索引查找元素"></a>Series 按指定索引查找元素</h4><pre><code>>>> s4.index # s4的索引Index(['a', 'b', 'c', 'd', 'e', 'B', 'C', 'D', 'E'], dtype='object')>>> s4.values # s4的值array([1, 2, 3, 4, 5, 1, 2, 3, 4], dtype=int64)>>> s4['B'] # 指定单个索引1>>> s4[['a','B']] # 指定多个索引a 1B 1>>> s4>3a Falseb Falsec Falsed Truee TrueB FalseC FalseD FalseE True>>> s4[s4>3] # 利用布尔型数组进行过滤Seriesd 4e 5E 4</code></pre><h4 id="Series-切片操作"><a href="#Series-切片操作" class="headerlink" title="Series 切片操作"></a>Series 切片操作</h4><pre><code>>>> s4[:3] # 对s4的前 3 个数据访问a 1b 2c 3</code></pre><h4 id="判断值是否为空"><a href="#判断值是否为空" class="headerlink" title="判断值是否为空"></a>判断值是否为空</h4><pre><code>>>> pd.isnull(s3) # 看Series的值为空a Falseb Falsec Falsed Falsee False>>> pd.notnull(s3) # 看Series的值不为空a Trueb Truec Trued Truee True>>> all(pd.notnull(s1 + s4)) # 所有为True才为真False>>> any(pd.notnull(s1 + s4)) # 有一个为True就为真True</code></pre><h4 id="给Series及其index取名"><a href="#给Series及其index取名" class="headerlink" title="给Series及其index取名"></a>给Series及其index取名</h4><pre><code>>>> s4.name = 'demo' # 给Series取名>>> s4a 1b 2c 3d 4e 5B 1C 2D 3E 4Name: demo, dtype: int64>>> s4.index.name = 'demo' # 给Series的索引取名>>> s4demoa 1b 2c 3d 4e 5B 1C 2D 3E 4Name: demo, dtype: int64</code></pre><h3 id="Series-运算"><a href="#Series-运算" class="headerlink" title="Series 运算"></a>Series 运算</h3><h4 id="Series-加法运算"><a href="#Series-加法运算" class="headerlink" title="Series 加法运算"></a>Series 加法运算</h4><p>Series 的加法运算是按照索引计算,如果索引不同则填充为 NaN(空值)。</p><pre><code>>>> s4a 1b 2c 3d 4e 5B 1C 2D 3E 4dtype: int64>>> s3a 1b 2c 3d 4e 5dtype: int64>>> s4.add(s3)B NaNC NaND NaNE NaNa 2.0b 4.0c 6.0d 8.0e 10.0</code></pre><h4 id="Series-减法运算"><a href="#Series-减法运算" class="headerlink" title="Series 减法运算"></a>Series 减法运算</h4><p>Series的减法运算是按照索引对应计算,如果不同则填充为 <code>NaN</code>(空值)。</p><pre><code>>>> s4.sub(s3)B NaNC NaND NaNE NaNa 0.0b 0.0c 0.0d 0.0e 0.0</code></pre><h4 id="Series-乘法运算"><a href="#Series-乘法运算" class="headerlink" title="Series 乘法运算"></a>Series 乘法运算</h4><p>Series 的乘法运算是按照索引对应计算,如果索引不同则填充为 NaN(空值)。</p><pre><code>>>> s4.mul(s3)B NaNC NaND NaNE NaNa 1.0b 4.0c 9.0d 16.0e 25.0dtype: float64>>> s3.mul(s3)a 1b 4c 9d 16e 25</code></pre><h4 id="Series-除法运算"><a href="#Series-除法运算" class="headerlink" title="Series 除法运算"></a>Series 除法运算</h4><p>Series 的除法运算是按照索引对应计算,如果索引不同则填充为 NaN(空值)。</p><pre><code>>>> s4.div(s3)B NaNC NaND NaNE NaNa 1.0b 1.0c 1.0d 1.0e 1.0</code></pre><h4 id="Series-求均值"><a href="#Series-求均值" class="headerlink" title="Series 求均值"></a>Series 求均值</h4><pre><code>>>> s4.median()3.0</code></pre><h4 id="Series-求和"><a href="#Series-求和" class="headerlink" title="Series 求和"></a>Series 求和</h4><pre><code>>>> s4.sum()25</code></pre><h4 id="Series-求最大值"><a href="#Series-求最大值" class="headerlink" title="Series 求最大值"></a>Series 求最大值</h4><pre><code>>>> s4.max()5</code></pre><h4 id="Series-求最小值"><a href="#Series-求最小值" class="headerlink" title="Series 求最小值"></a>Series 求最小值</h4><pre><code>>>> s4.min()1</code></pre><h2 id="DataFrame"><a href="#DataFrame" class="headerlink" title="DataFrame"></a>DataFrame</h2><blockquote><p>与 Sereis 不同,DataFrame 可以存在多列数据。一般情况下,DataFrame 也更加常用。</p></blockquote><h3 id="创建-DataFrame-数据类型"><a href="#创建-DataFrame-数据类型" class="headerlink" title="创建 DataFrame 数据类型"></a>创建 DataFrame 数据类型</h3><h4 id="通过-NumPy-数组创建-DataFrame"><a href="#通过-NumPy-数组创建-DataFrame" class="headerlink" title="通过 NumPy 数组创建 DataFrame"></a>通过 NumPy 数组创建 DataFrame</h4><pre><code>>>> dates = pd.date_range('today',periods=6) # 定义时间序列作为 index>>> datesDatetimeIndex(['2018-04-26 11:37:07.705264', '2018-04-27 11:37:07.705264', '2018-04-28 11:37:07.705264', '2018-04-29 11:37:07.705264', '2018-04-30 11:37:07.705264', '2018-05-01 11:37:07.705264'], dtype='datetime64[ns]', freq='D')>>> num_arr = np.random.randn(6,4) # 传入 numpy 随机数组>>>>>> columns = ['A','B','C','D'] # 将列表作为列名>>>>>> df1 = pd.DataFrame(num_arr,index=dates,columns=columns)>>>>>> df1 A B C D2018-04-26 11:37:07.705264 -0.400285 0.951334 0.385495 0.9558692018-04-27 11:37:07.705264 -0.462783 1.237563 0.083758 0.1109432018-04-28 11:37:07.705264 -0.763846 1.085889 0.541877 0.9612612018-04-29 11:37:07.705264 0.308832 2.252399 0.882554 0.0265902018-04-30 11:37:07.705264 -0.007068 0.028647 0.155501 -0.2429962018-05-01 11:37:07.705264 0.047310 0.797592 1.203195 -0.236018</code></pre><h4 id="通过字典数组创建-DataFrame"><a href="#通过字典数组创建-DataFrame" class="headerlink" title="通过字典数组创建 DataFrame"></a>通过字典数组创建 DataFrame</h4><pre><code>>>> data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'], 'age': [2.5, 3, 0.5, np.nan, 5, 2, 4.5, np.nan, 7, 3], 'visits': [1, 3, 2, 3, 2, 3, 1, 1, 2, 1], 'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']}>>> labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']>>> df2 = pd.DataFrame(data, index=labels)>>> df2 age animal priority visitsa 2.5 cat yes 1b 3.0 cat yes 3c 0.5 snake no 2d NaN dog yes 3e 5.0 dog no 2f 2.0 cat no 3g 4.5 snake no 1h NaN cat yes 1i 7.0 dog no 2j 3.0 dog no 1</code></pre><h3 id="DataFrame-基本操作"><a href="#DataFrame-基本操作" class="headerlink" title="DataFrame 基本操作"></a>DataFrame 基本操作</h3><h4 id="查看-DataFrame-属性"><a href="#查看-DataFrame-属性" class="headerlink" title="查看 DataFrame 属性"></a>查看 DataFrame 属性</h4><pre><code>>>> df2.dtypes # 数据类型age float64animal objectpriority objectvisits int64>>> df2.index # 行索引(行标签)Index(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], dtype='object')>>> df2.columns # 列标签Index(['age', 'animal', 'priority', 'visits'], dtype='object')>>> df2.values # DataFrame 数据array([[2.5, 'cat', 'yes', 1], [3.0, 'cat', 'yes', 3], [0.5, 'snake', 'no', 2], [nan, 'dog', 'yes', 3], [5.0, 'dog', 'no', 2], [2.0, 'cat', 'no', 3], [4.5, 'snake', 'no', 1], [nan, 'cat', 'yes', 1], [7.0, 'dog', 'no', 2], [3.0, 'dog', 'no', 1]], dtype=object)>>> df2.shape # DataFrame 形状(10, 4)>>> df2.size # DataFrame 元素个数40>>> len(df2) # DataFrame 行数10</code></pre><h4 id="查看-DataFrame-的统计数据"><a href="#查看-DataFrame-的统计数据" class="headerlink" title="查看 DataFrame 的统计数据"></a>查看 DataFrame 的统计数据</h4><pre><code>>>> df2 age animal priority visitsa 2.5 cat yes 1b 3.0 cat yes 3c 0.5 snake no 2d NaN dog yes 3e 5.0 dog no 2f 2.0 cat no 3g 4.5 snake no 1h NaN cat yes 1i 7.0 dog no 2j 3.0 dog no 1</code></pre><h4 id="DataFrame-转置操作"><a href="#DataFrame-转置操作" class="headerlink" title="DataFrame 转置操作"></a>DataFrame 转置操作</h4><pre><code>>>> df2.T a b c d e f g h i jage 2.5 3 0.5 NaN 5 2 4.5 NaN 7 3animal cat cat snake dog dog cat snake cat dog dogpriority yes yes no yes no no no yes no novisits 1 3 2 3 2 3 1 1 2 1</code></pre><h4 id="DataFrame-求平均值操作"><a href="#DataFrame-求平均值操作" class="headerlink" title="DataFrame 求平均值操作"></a>DataFrame 求平均值操作</h4><pre><code>>>> df3.mean()age 3.25visits 1.90No. 4.50dtype: float64</code></pre><h4 id="对-DataFrame-中任意列做求和操作"><a href="#对-DataFrame-中任意列做求和操作" class="headerlink" title="对 DataFrame 中任意列做求和操作"></a>对 DataFrame 中任意列做求和操作</h4><pre><code>>>> df3['visits'].sum()19</code></pre><h4 id="对-DataFrame-进行排序"><a href="#对-DataFrame-进行排序" class="headerlink" title="对 DataFrame 进行排序"></a>对 DataFrame 进行排序</h4><pre><code>>>> df2.sort_values('age',ascending=True) # 按 age 升序排列,默认ascending为True age animal priority visitsc 0.5 snake no 2f 2.0 cat no 3a 2.5 cat yes 1b 3.0 cat yes 3j 3.0 dog no 1g 4.5 snake no 1e 5.0 dog no 2i 7.0 dog no 2d NaN dog yes 3h NaN cat yes 1>>> df2.sort_index() # 按索引进行排序 age animal priority visitsa 2.5 cat yes 1b 3.0 cat yes 3c 0.5 snake no 2d NaN dog yes 3e 5.0 dog no 2f 2.0 cat no 3g 4.5 snake no 1h NaN cat yes 1i 7.0 dog no 2j 3.0 dog no 1</code></pre><h4 id="DataFrame-副本拷贝"><a href="#DataFrame-副本拷贝" class="headerlink" title="DataFrame 副本拷贝"></a>DataFrame 副本拷贝</h4><pre><code>>>> df3 = df2.copy()>>> df3 age animal priority visitsa 2.5 cat yes 1b 3.0 cat yes 3c 0.5 snake no 2d NaN dog yes 3e 5.0 dog no 2f 2.0 cat no 3g 4.5 snake no 1h NaN cat yes 1i 7.0 dog no 2j 3.0 dog no 1</code></pre><h4 id="判断-DataFrame-元素是否为空"><a href="#判断-DataFrame-元素是否为空" class="headerlink" title="判断 DataFrame 元素是否为空"></a>判断 DataFrame 元素是否为空</h4><pre><code>>>> df3.isnull() # 如果为空则返回为 True age animal priority visitsa False False False Falseb False False False Falsec False False False Falsed True False False Falsee False False False Falsef False False False Falseg False False False Falseh True False False Falsei False False False Falsej False False False False</code></pre><h3 id="查询与索引切片"><a href="#查询与索引切片" class="headerlink" title="查询与索引切片"></a>查询与索引切片</h3><h4 id="预览-DataFrame-的前-5-行数据"><a href="#预览-DataFrame-的前-5-行数据" class="headerlink" title="预览 DataFrame 的前 5 行数据"></a>预览 DataFrame 的前 5 行数据</h4><pre><code>>>> df2.head() # 默认为显示 5 行,可根据需要在括号中填入希望预览的行数 age animal priority visitsa 2.5 cat yes 1b 3.0 cat yes 3c 0.5 snake no 2d NaN dog yes 3e 5.0 dog no 2</code></pre><h4 id="查看-DataFrame-的后-3-行数据"><a href="#查看-DataFrame-的后-3-行数据" class="headerlink" title="查看 DataFrame 的后 3 行数据"></a>查看 DataFrame 的后 3 行数据</h4><pre><code>>>> df2.tail(3) age animal priority visitsh NaN cat yes 1i 7.0 dog no 2j 3.0 dog no</code></pre><h4 id="对-DataFrame-数据切片-相当于多行-依据索引切片"><a href="#对-DataFrame-数据切片-相当于多行-依据索引切片" class="headerlink" title="对 DataFrame 数据切片(相当于多行,依据索引切片)"></a>对 DataFrame 数据切片(相当于多行,依据索引切片)</h4><pre><code>>>> df2[1:3] age animal priority visitsb 3.0 cat yes 3c 0.5 snake no 2</code></pre><h4 id="对-DataFrame-通过标签查询(单列)"><a href="#对-DataFrame-通过标签查询(单列)" class="headerlink" title="对 DataFrame 通过标签查询(单列)"></a>对 DataFrame 通过标签查询(单列)</h4><pre><code>>>> df2['age']a 2.5b 3.0c 0.5d NaNe 5.0f 2.0g 4.5h NaNi 7.0j 3.0>>> df2.age # 等价于 df2['age']a 2.5b 3.0c 0.5d NaNe 5.0f 2.0g 4.5h NaNi 7.0j 3.0</code></pre><h4 id="对-DataFrame-通过标签查询-多列"><a href="#对-DataFrame-通过标签查询-多列" class="headerlink" title="对 DataFrame 通过标签查询(多列)"></a>对 DataFrame 通过标签查询(多列)</h4><pre><code>>>> df2[['age','animal']] # 传入一个列名组成的列表 age animala 2.5 catb 3.0 catc 0.5 snaked NaN doge 5.0 dogf 2.0 catg 4.5 snakeh NaN cati 7.0 dogj 3.0 dog</code></pre><h4 id="对-DataFrame-通过索引位置查询"><a href="#对-DataFrame-通过索引位置查询" class="headerlink" title="对 DataFrame 通过索引位置查询"></a>对 DataFrame 通过索引位置查询</h4><pre><code>>>> df2.iloc[1:3,0:2] # [行索引,列索引] age animal priority visits b 3.0 cat yes 3 c 0.5 snake no 2</code></pre><h4 id="对-DataFrame-通过标签-label-name"><a href="#对-DataFrame-通过标签-label-name" class="headerlink" title="对 DataFrame 通过标签 label_name"></a>对 DataFrame 通过标签 label_name</h4><pre><code>>>> df2.loc['a':'f','age':'visits'] age animal priority visitsa 2.5 cat yes 1b 3.0 cat yes 3c 0.5 snake no 2d NaN dog yes 3e 5.0 dog no 2f 2.0 cat no 3</code></pre><h3 id="数据填充修改与删除"><a href="#数据填充修改与删除" class="headerlink" title="数据填充修改与删除"></a>数据填充修改与删除</h3><h4 id="添加列数据"><a href="#添加列数据" class="headerlink" title="添加列数据"></a>添加列数据</h4><pre><code>>>> num=pd.Series([0,1,2,3,4,5,6,7,8,9],index=df3.index)>>> numa 0b 1c 2d 3e 4f 5g 6h 7i 8j 9dtype: int64>>> df3['No.'] = num # 添加以 'No.' 为列名的新数据列>>> df3 age animal priority visits No.a 2.5 cat yes 1 0b 3.0 cat yes 3 1c 0.5 snake no 2 2d NaN dog yes 3 3e 5.0 dog no 2 4f 2.0 cat no 3 5g 4.5 snake no 1 6h NaN cat yes 1 7i 7.0 dog no 2 8j 3.0 dog no 1 9</code></pre><h4 id="只给某列的某些数据赋值-指定索引"><a href="#只给某列的某些数据赋值-指定索引" class="headerlink" title="只给某列的某些数据赋值,指定索引"></a>只给某列的某些数据赋值,指定索引</h4><pre><code>>>> df3['new'] = pd.Series([500,600],index=['a','b'])>>> df3 age animal priority visits No. newa 2.5 cat yes 1 0 500.0b 2.0 cat yes 3 1 600.0c 0.5 snake no 2 2 NaNd NaN dog yes 3 3 NaNe 5.0 dog no 2 4 NaNf 1.5 cat no 3 5 NaNg 4.5 snake no 1 6 NaNh NaN cat yes 1 7 NaNi 7.0 dog no 2 8 NaNj 3.0 dog no 1 9 NaN</code></pre><h4 id="删除指定的列’new’"><a href="#删除指定的列’new’" class="headerlink" title="删除指定的列’new’"></a>删除指定的列’new’</h4><pre><code>>>> df3.drop('new',axis=1) age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2d NaN dog yes 3 3e 5.0 dog no 2 4f 1.5 cat no 3 5g 4.5 snake no 1 6h NaN cat yes 1 7i 7.0 dog no 2 8j 3.0 dog no 1 9</code></pre><h4 id="删除指定的行’j’"><a href="#删除指定的行’j’" class="headerlink" title="删除指定的行’j’"></a>删除指定的行’j’</h4><pre><code>>>> df3.drop('j',axis=0) age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2d NaN dog yes 3 3e 5.0 dog no 2 4f 1.5 cat no 3 5g 4.5 snake no 1 6h NaN cat yes 1 7i 7.0 dog no 2 8</code></pre><h4 id="根据-DataFrame-的下标值进行更改。"><a href="#根据-DataFrame-的下标值进行更改。" class="headerlink" title="根据 DataFrame 的下标值进行更改。"></a>根据 DataFrame 的下标值进行更改。</h4><pre><code>>>> # 修改第 2 行与第 1 列对应的值 3.0 → 2.0>>> df3.iat[1,0] = 2 # 索引序号从 0 开始,这里为 1, 0>>> df3 age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2d NaN dog yes 3 3e 5.0 dog no 2 4f 2.0 cat no 3 5g 4.5 snake no 1 6h NaN cat yes 1 7i 7.0 dog no 2 8j 3.0 dog no 1 9</code></pre><h4 id="根据-DataFrame-的标签对数据进行修改"><a href="#根据-DataFrame-的标签对数据进行修改" class="headerlink" title="根据 DataFrame 的标签对数据进行修改"></a>根据 DataFrame 的标签对数据进行修改</h4><pre><code>>>> df3.loc['f','age']=1.5>>> df3 age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2d NaN dog yes 3 3e 5.0 dog no 2 4f 1.5 cat no 3 5g 4.5 snake no 1 6h NaN cat yes 1 7i 7.0 dog no 2 8j 3.0 dog no 1 9</code></pre><h3 id="DataFrame-缺失值操作"><a href="#DataFrame-缺失值操作" class="headerlink" title="DataFrame 缺失值操作"></a>DataFrame 缺失值操作</h3><h4 id="对缺失值进行填充"><a href="#对缺失值进行填充" class="headerlink" title="对缺失值进行填充"></a>对缺失值进行填充</h4><pre><code>>>> df4=df3.copy()>>> print(df4) age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2d NaN dog yes 3 3e 5.0 dog no 2 4f 1.5 cat no 3 5g 4.5 snake no 1 6h NaN cat yes 1 7i 7.0 dog no 2 8j 3.0 dog no 1 9>>> df4.fillna(value=3) age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2d 3.0 dog yes 3 3e 5.0 dog no 2 4f 1.5 cat no 3 5g 4.5 snake no 1 6h 3.0 cat yes 1 7i 7.0 dog no 2 8j 3.0 dog no 1 9</code></pre><h4 id="删除存在缺失值的行"><a href="#删除存在缺失值的行" class="headerlink" title="删除存在缺失值的行"></a>删除存在缺失值的行</h4><pre><code>>>> df5.dropna(how='any') # 任何存在 NaN 的行都将被删除 age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2e 5.0 dog no 2 4f 1.5 cat no 3 5g 4.5 snake no 1 6i 7.0 dog no 2 8j 3.0 dog no 1 9</code></pre><h3 id="多级index-Series-amp-amp-DataFrame"><a href="#多级index-Series-amp-amp-DataFrame" class="headerlink" title="多级index Series && DataFrame"></a>多级index Series && DataFrame</h3><h4 id="多级index-Series"><a href="#多级index-Series" class="headerlink" title="多级index Series"></a>多级index Series</h4><pre><code>>>> s1 = Series(np.random.randn(6), index=[['1','1','1','2','2','2'],['a','b','c','a','b','c']]) # 创建一个多级index的Series>>> print(s1)1 a -1.690157 b 0.835443 c 1.1870042 a 1.130990 b -0.167736 c -0.062882>>> s1['1'] # 访问第一级a -1.690157b 0.835443c 1.187004>>> s1[:,'a'] # 访问每一级的'a'1 -1.6901572 1.130990>>> df1 = s1.unstack() # 多级index的 series转换为 DataFrame>>> df1 a b c1 -1.690157 0.835443 1.1870042 1.130990 -0.167736 -0.062882>>> df2 = DataFrame([s1['1'],s1['2']]) # 多级index的 series转换为 DataFrame>>> df2 a b c0 -1.690157 0.835443 1.1870041 1.130990 -0.167736 -0.062882>>> s2 = df1.unstack() # DataFrame转换成多级索引的Series>>> s2a 1 -1.690157 2 1.130990b 1 0.835443 2 -0.167736c 1 1.187004 2 -0.062882</code></pre><h4 id="多级索引的DataFrame"><a href="#多级索引的DataFrame" class="headerlink" title="多级索引的DataFrame"></a>多级索引的DataFrame</h4><pre><code>>>> df = DataFrame(np.arange(16).reshape(4,4),index = [['a','a','b','b'],['1','2','1','2']])>>> df 0 1 2 3a 1 0 1 2 3 2 4 5 6 7b 1 8 9 10 11 2 12 13 14 15>>> df = DataFrame(np.arange(20).reshape(5,4),index = [['a','a','b','b','c'],['1','2','1','2','3']], columns = [['BJ','BJ','SH','GZ'],[8,9,8,8]])>>> df BJ SH GZ 8 9 8 8a 1 0 1 2 3 2 4 5 6 7b 1 8 9 10 11 2 12 13 14 15c 3 16 17 18 19>>> df['BJ'][8]a 1 0 2 4b 1 8 2 12c 3 16>>> df['BJ'][9]['a']['1']1</code></pre><h3 id="DataFrame-文件操作"><a href="#DataFrame-文件操作" class="headerlink" title="DataFrame 文件操作"></a>DataFrame 文件操作</h3><h4 id="CSV-文件写入"><a href="#CSV-文件写入" class="headerlink" title="CSV 文件写入"></a>CSV 文件写入</h4><pre><code>>>> df3.to_csv('animal.csv')</code></pre><h4 id="CSV-文件读取"><a href="#CSV-文件读取" class="headerlink" title="CSV 文件读取"></a>CSV 文件读取</h4><pre><code>>>> df_animal=pd.read_csv('animal.csv')</code></pre><h4 id="Excel-写入操作"><a href="#Excel-写入操作" class="headerlink" title="Excel 写入操作"></a>Excel 写入操作</h4><pre><code>>>> df3.to_excel('animal.xlsx', sheet_name='Sheet1')</code></pre><h4 id="Excel-读取操作"><a href="#Excel-读取操作" class="headerlink" title="Excel 读取操作"></a>Excel 读取操作</h4><pre><code>>>> pd.read_excel('animal.xlsx', 'Sheet1', index_col=None, na_values=['NA']) age animal priority visits No.a 2.5 cat yes 1 0b 2.0 cat yes 3 1c 0.5 snake no 2 2d NaN dog yes 3 3e 5.0 dog no 2 4f 1.5 cat no 3 5g 4.5 snake no 1 6h NaN cat yes 1 7i 7.0 dog no 2 8j 3.0 dog no 1 9</code></pre>]]></content>
<summary type="html">
<blockquote>
<p>Pandas 是基于 NumPy 的一种数据处理工具,该工具为了解决数据分析任务而创建。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的函数和方法。</p>
</blockquote>
<h2 id="Pandas的常用数据结构"><a href="#Pandas的常用数据结构" class="headerlink" title="Pandas的常用数据结构"></a>Pandas的常用数据结构</h2><p>Pandas 的数据结构:Pandas 主要有 Series(一维数组),DataFrame(二维数组),Panel(三维数组),Panel4D(四维数组),PanelND(更多维数组)等数据结构。其中 Series 和 DataFrame 应用的最为广泛。</p>
<ul>
<li>Series 是一维带标签的数组,它可以包含任何数据类型。包括整数,字符串,浮点数,Python 对象等。Series 可以通过标签来定位。</li>
<li>DataFrame 是二维的带标签的数据结构。我们可以通过标签来定位数据。这是 NumPy 所没有的。</li>
</ul>
<h2 id="Series"><a href="#Series" class="headerlink" title="Series"></a>Series</h2><blockquote>
<p>Pandas 中,Series 可以被看作由 1 列数据组成的数据集。</p>
</blockquote>
<h3 id="创建-Series数据类型"><a href="#创建-Series数据类型" class="headerlink" title="创建 Series数据类型"></a>创建 Series数据类型</h3><p>创建 Series 语法: <code>s = pd.Series(data, index=index)</code>,可以通过多种方式进行创建, 这里的data的数据类型只要是序列都可以。</p>
</summary>
<category term="python数据分析" scheme="http://www.chenfanlinux.org/categories/python%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/"/>
<category term="Pandas" scheme="http://www.chenfanlinux.org/tags/Pandas/"/>
</entry>
</feed>