python基础篇【第十篇】多路复用、多线程

一、小知识点(作用域)

进入主题之前先分享一个有关某公司一道python自动化的面试题:

首先说一下作用域的关系,如以下案例:

if 1==1:
    name="tom"
print(name)

看以上代码你觉得会打印出来"tom"吗?

答案是:会的。

这个地方需要了解的是,在Java、c#是有块级作用域的,不会打印出来。在python中无块级作用域可以会被执行

既然已经了解python中无块级作用域,就要了解变量执行的优先级,先从自己本身作用域找,找不到往上一级找,以此类推。

那么我们在了解一个案例:

name ="tom"
def f1():
    print(name)

def f2():
    name="jerry"
    f1()
f2()

你觉得name会是什么? tom or jerry。

答案是:tom    why?  一脸懵逼!!!

原理:在python中 作用域在执行之前已经确定,这就好理解了

好了,下面就说一下某浪公司的面试题:

实例1:

line=[x+100 for x in range(10)]
#意思是循环0-9 每个数加100 生成一个新的列表
print(line)

#显示结果
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]

实例2:

ll=[x+100 for x in range(10) if x>6]
#意思是循环0-9 当x>6时 加100
print(ll)

#显示结果
[107, 108, 109]

按照上面的两个列子,x+100 也可以写成是一个函数如:

line=[lambda :x for x in range(10)]
r= line[0]()
print(r)

结果会是什么? 0 or None or lambda:x ??

答案是:9     why?  两脸懵逼!!!

原理:函数在没有执行之前内部代码不执行

那么line列表中就有十个 lambda :x

那就找 x 是多少就行了 ,很明显循环到最后一次时x被重新复制给 9,那么lambda表达式直接return x

这就是某浪的一道面试题。。。。

二、socketserver源码剖析

继续上一篇socketserver往下说,上一篇只是知道了具体的用法,但是不知道什么意思,下面我们来源码剖析。。。

 1 import subprocess
 2 class MyServer(socketserver.BaseRequestHandler):
 3     def handle(self):
 4         self.request.sendall(bytes("欢迎光临",encoding="utf-8"))
 5         while True:
 6                 data=self.request.recv(1024)
 7                 if len(data) ==0:break
 8                 print("[%s] says:%s" %(self.client_address,data.decode()))
 9                 cmd= subprocess.Popen(data.decode(),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
10                 cmd_res=cmd.stdout.read()
11                 if not cmd_res:
12                     cmd_data=bytes(cmd.stderr.read())
13                 if len(cmd_res)==0:
14                     cmd_data=bytes("err cmd",encoding="utf8")
15                 self.request.send(cmd_res)
16
17
18 if __name__==‘__main__‘:
19     server=socketserver.ThreadingTCPServer((‘127.0.0.1‘,8009),MyServer)
20     server.serve_forever()

ThreadingTCPServer的类图关系如下:

以上面的代码为例内部调用流程为:

  • 启动服务端程序
  • 执行 TCPServer.__init__ 方法,创建服务端Socket对象并绑定 IP 和 端口
  • 执行 BaseServer.__init__ 方法,将自定义的继承自socketserver.BaseRequestHandler 的类MyServer赋值给 self.RequestHandlerClass
  • 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...
  • 执行 handle_request_noblock()
  • 当客户端连接到达服务器
  • 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
  • 执行 ThreadingMixIn.process_request_thread 方法
  • 执行 BaseServer.finish_request 方法,
  • 执行 self.RequestHandlerClass()  即:执行 自定义 MyServer 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyServer的handle方法)

class BaseServer:

    """Base class for server classes.

    Methods for the caller:

    - __init__(server_address, RequestHandlerClass)
    - serve_forever(poll_interval=0.5)
    - shutdown()
    - handle_request()  # if you do not use serve_forever()
    - fileno() -> int   # for select()

    Methods that may be overridden:

    - server_bind()
    - server_activate()
    - get_request() -> request, client_address
    - handle_timeout()
    - verify_request(request, client_address)
    - server_close()
    - process_request(request, client_address)
    - shutdown_request(request)
    - close_request(request)
    - handle_error()

    Methods for derived classes:

    - finish_request(request, client_address)

    Class variables that may be overridden by derived classes or
    instances:

    - timeout
    - address_family
    - socket_type
    - allow_reuse_address

    Instance variables:

    - RequestHandlerClass
    - socket

    """

    timeout = None

    def __init__(self, server_address, RequestHandlerClass):
        """Constructor.  May be extended, do not override."""
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.__is_shut_down = threading.Event()
        self.__shutdown_request = False

    def server_activate(self):
        """Called by constructor to activate the server.

        May be overridden.

        """
        pass

    def serve_forever(self, poll_interval=0.5):
        """Handle one request at a time until shutdown.

        Polls for shutdown every poll_interval seconds. Ignores
        self.timeout. If you need to do periodic tasks, do them in
        another thread.
        """
        self.__is_shut_down.clear()
        try:
            while not self.__shutdown_request:
                # XXX: Consider using another file descriptor or
                # connecting to the socket to wake this up instead of
                # polling. Polling reduces our responsiveness to a
                # shutdown request and wastes cpu at all other times.
                r, w, e = _eintr_retry(select.select, [self], [], [],
                                       poll_interval)
                if self in r:
                    self._handle_request_noblock()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()

    def shutdown(self):
        """Stops the serve_forever loop.

        Blocks until the loop has finished. This must be called while
        serve_forever() is running in another thread, or it will
        deadlock.
        """
        self.__shutdown_request = True
        self.__is_shut_down.wait()

    # The distinction between handling, getting, processing and
    # finishing a request is fairly arbitrary.  Remember:
    #
    # - handle_request() is the top-level call.  It calls
    #   select, get_request(), verify_request() and process_request()
    # - get_request() is different for stream or datagram sockets
    # - process_request() is the place that may fork a new process
    #   or create a new thread to finish the request
    # - finish_request() instantiates the request handler class;
    #   this constructor will handle the request all by itself

    def handle_request(self):
        """Handle one request, possibly blocking.

        Respects self.timeout.
        """
        # Support people who used socket.settimeout() to escape
        # handle_request before self.timeout was available.
        timeout = self.socket.gettimeout()
        if timeout is None:
            timeout = self.timeout
        elif self.timeout is not None:
            timeout = min(timeout, self.timeout)
        fd_sets = _eintr_retry(select.select, [self], [], [], timeout)
        if not fd_sets[0]:
            self.handle_timeout()
            return
        self._handle_request_noblock()

    def _handle_request_noblock(self):
        """Handle one request, without blocking.

        I assume that select.select has returned that the socket is
        readable before this function was called, so there should be
        no risk of blocking in get_request().
        """
        try:
            request, client_address = self.get_request()
        except socket.error:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)
            except:
                self.handle_error(request, client_address)
                self.shutdown_request(request)

    def handle_timeout(self):
        """Called if no new request arrives within self.timeout.

        Overridden by ForkingMixIn.
        """
        pass

    def verify_request(self, request, client_address):
        """Verify the request.  May be overridden.

        Return True if we should proceed with this request.

        """
        return True

    def process_request(self, request, client_address):
        """Call finish_request.

        Overridden by ForkingMixIn and ThreadingMixIn.

        """
        self.finish_request(request, client_address)
        self.shutdown_request(request)

    def server_close(self):
        """Called to clean-up the server.

        May be overridden.

        """
        pass

    def finish_request(self, request, client_address):
        """Finish one request by instantiating RequestHandlerClass."""
        self.RequestHandlerClass(request, client_address, self)

    def shutdown_request(self, request):
        """Called to shutdown and close an individual request."""
        self.close_request(request)

    def close_request(self, request):
        """Called to clean up an individual request."""
        pass

    def handle_error(self, request, client_address):
        """Handle an error gracefully.  May be overridden.

        The default is to print a traceback and continue.

        """
        print ‘-‘*40
        print ‘Exception happened during processing of request from‘,
        print client_address
        import traceback
        traceback.print_exc() # XXX But this goes to stderr!
        print ‘-‘*40

BaseServer

BaseServer

class TCPServer(BaseServer):

    """Base class for various socket-based server classes.

    Defaults to synchronous IP stream (i.e., TCP).

    Methods for the caller:

    - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
    - serve_forever(poll_interval=0.5)
    - shutdown()
    - handle_request()  # if you don‘t use serve_forever()
    - fileno() -> int   # for select()

    Methods that may be overridden:

    - server_bind()
    - server_activate()
    - get_request() -> request, client_address
    - handle_timeout()
    - verify_request(request, client_address)
    - process_request(request, client_address)
    - shutdown_request(request)
    - close_request(request)
    - handle_error()

    Methods for derived classes:

    - finish_request(request, client_address)

    Class variables that may be overridden by derived classes or
    instances:

    - timeout
    - address_family
    - socket_type
    - request_queue_size (only for stream sockets)
    - allow_reuse_address

    Instance variables:

    - server_address
    - RequestHandlerClass
    - socket

    """

    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    request_queue_size = 5

    allow_reuse_address = False

    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        BaseServer.__init__(self, server_address, RequestHandlerClass)
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

    def server_bind(self):
        """Called by constructor to bind the socket.

        May be overridden.

        """
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
        self.server_address = self.socket.getsockname()

    def server_activate(self):
        """Called by constructor to activate the server.

        May be overridden.

        """
        self.socket.listen(self.request_queue_size)

    def server_close(self):
        """Called to clean-up the server.

        May be overridden.

        """
        self.socket.close()

    def fileno(self):
        """Return socket file number.

        Interface required by select().

        """
        return self.socket.fileno()

    def get_request(self):
        """Get the request and client address from the socket.

        May be overridden.

        """
        return self.socket.accept()

    def shutdown_request(self, request):
        """Called to shutdown and close an individual request."""
        try:
            #explicitly shutdown.  socket.close() merely releases
            #the socket and waits for GC to perform the actual close.
            request.shutdown(socket.SHUT_WR)
        except socket.error:
            pass #some platforms may raise ENOTCONN here
        self.close_request(request)

    def close_request(self, request):
        """Called to clean up an individual request."""
        request.close()

TCPServer

TCPServer源码

class ThreadingMixIn:
    """Mix-in class to handle each request in a new thread."""

    # Decides how threads will act upon termination of the
    # main process
    daemon_threads = False

    def process_request_thread(self, request, client_address):
        """Same as in BaseServer but as a thread.

        In addition, exception handling is done here.

        """
        try:
            self.finish_request(request, client_address)
            self.shutdown_request(request)
        except:
            self.handle_error(request, client_address)
            self.shutdown_request(request)

    def process_request(self, request, client_address):
        """Start a new thread to process the request."""
        t = threading.Thread(target = self.process_request_thread,
                             args = (request, client_address))
        t.daemon = self.daemon_threads
        t.start()

ThreadingMixIn

ThreadingMixIn源码

class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

ThreadingTCPServer源码

class BaseRequestHandler:

    """Base class for request handler classes.

    This class is instantiated for each request to be handled.  The
    constructor sets the instance variables request, client_address
    and server, and then calls the handle() method.  To implement a
    specific service, all you need to do is to derive a class which
    defines a handle() method.

    The handle() method can find the request as self.request, the
    client address as self.client_address, and the server (in case it
    needs access to per-server information) as self.server.  Since a
    separate instance is created for each request, the handle() method
    can define arbitrary other instance variariables.

    """

    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server
        self.setup()
        try:
            self.handle()
        finally:
            self.finish()

    def setup(self):
        pass

    def handle(self):
        pass

    def finish(self):
        pass

SocketServer.BaseRequestHandler

BaseRequestHandler源码

三、I/O多路复用

I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。注意(I/O是不占用cpu的)

Linux中的 select,poll,epoll 都是IO多路复用的机制。

 1 select
 2
 3 select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。
 4 select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一。
 5 select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。
 6 另外,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。同时,由于网络响应时间的延迟使得大量TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。
 7
 8 poll
 9
10 poll在1986年诞生于System V Release 3,它和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制。
11 poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
12 另外,select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为水平触发(Level Triggered)。
13
14 epoll
15
16 直到Linux2.6才出现了由内核直接支持的实现方法,那就是epoll,它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。
17 epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。
18 epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。
19 另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。

介绍

在Windows 和Mac 系统中 python只提供了select一种IO多路复用的机制

在linux中  select,poll,epoll 都是支持的

 注意:网络操作、文件操作、终端操作等均属于IO操作,对于windows只支持Socket操作,其他系统支持其他IO操作,但是无法检测 普通文件操作 自动上次读取是否已经变化。

用select实现socket多线路连接

书写格式如下例:

server端:

import socket
import select
sk=socket.socket()
sk.bind(("127.0.0.1",8888))
sk.listen(5)
while True:
    rlist,wlist,elist=select.select([sk,],[],[],1)
    print(rlist)   #rlist中是socket 对象列表 【sk】
    for i in rlist:
        conn,addr=i.accept()
        conn.sendall(bytes("hello",encoding="utf8"))

client端:

import socket
sk=socket.socket()
sk.connect(("127.0.0.1",8888))
data=sk.recv(1024)
print(data.decode())
while True:
    input(">>>>")
sk.close()

server端详解:

句柄列表rlist, 句柄列表wlist, 句柄列表elist = select.select([sk], 句柄序列2, 句柄序列3, 1是超时时间)

参数: 可接受四个参数(前三个必须)
返回值:三个列表

select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。
1、当 参数sk序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中
2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中
3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中
4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化
   当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。

实例二:

server端

import socket
import select
sk=socket.socket()
sk.bind(("127.0.0.1",8888))
sk.listen(5)

inputs=[sk,]

outputs=[]
while True:
    rlist,wlist,e=select.select(inputs,outputs,[],1)
    print(len(inputs),len(rlist),len(outputs),len(wlist))   #rlist中是socket 对象列表 【sk】
    #打印的第一个参数是 公有多少个连接,2,变化的rlist个数, 3,有操作变化个数,4,也是有操作变化个数
    for i in rlist:   #循环这个句柄,只要inputs,有变化,rlist就能取到
        if i == sk:    #判断是否相等sk,相等话证明就会有新的连接
            conn,addr=i.accept()   #然后建立连接
            inputs.append(conn)    #把此次连接的线路也进行监听
            conn.sendall(bytes("hello",encoding="utf8"))    #发送给客户端一个信息验证
        else:     #如果不等,就有可能是线路发生了变化
            try:   #程序运行正确
                data=i.recv(1024)   #接收客户端信息
                print(data.decode())
                if not data:        #
                    raise Exception("断开连接")
                else:           #一些运行正常 ,把此次线路变化加到outputs列表中
                    outputs.append(i)
            except Exception as e:  #如果有程序退出, 也需要把此次线路变化从监听中删除
                print(e)
                inputs.remove(i)
    for w in wlist:    #wlist 有变化证明接收到信息,
        w.sendall(bytes("response",encoding="utf8"))    # 给客户端回个信息
        outputs.remove(w)  #然后删除此次监听,实现读写分离作用

client端:

import socket
sk=socket.socket()
sk.connect(("127.0.0.1",8888))
data=sk.recv(1024)
print(data.decode())
while True:
    intt=input(">>>>")
    sk.sendall(bytes(intt,encoding="utf8"))
    print(sk.recv(1024))
sk.close()

其实用select,并不是真正实现并发,一直循环着在监听数据是否有变化,并把数据处理完毕之后才会去处理新的请求数据。如果每个请求的耗时比较长时,select版本的服务器端也无法完成同时操作,这种模式称之为伪并发。

四、多线程、多进程

1. 一个应用程序可以有多进程、多线程
2. 默认是单进程、单线程
3. 单进程,多线程,在Python中不会性能提升,在Java和C#中可以提升。
提高并发:
多线程: IO操作,不会用到CPU,效率提升是可以的

多进程:计算型操作, 需要占用CPU,因此性能不会有提升

在程序猿的世界中,线程和进程是一个很重要的概念,很多人经常弄不清线程和进程到底是什么,有什么区别,本文试图来解释一下线程和进程。首先来看一下概念:

进程(英语:process):

是计算机中已运行程序的实体。进程为曾经是分时系统的基本运作单位。在面向进程设计的系统(如早期的UNIX,Linux 2.4及更早的版本)中,进程是程序的基本执行实体;在面向线程设计的系统(如当代多数操作系统、Linux 2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。

线程(英语:thread):

是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务

概念太吓人了,先来看一下进程,这个相对于线程来说还是稍微好理解一点的。进程,是程序运行的实体,这句话的意思是,程序是存放在硬盘中的,当这个程序运行时,就会产生若干个进程,并且这个进程是可见的

那么什么是 线程呢,线程是一个任务流,它被包含在进程之中

下面来看一下python中线程:

 1 import threading
 2 import time
 3 def f1(arg):
 4     time.sleep(5)  #等待5秒钟
 5     print(arg)     #执行
 6 t = threading.Thread(target=f1,args=(123,))
 7 t.setDaemon(True)   #True 表示主线程不等此子线程
 8 t.start()  #不代表当前线程会被立即执行
 9 t.join(6)  #表示主线程到此,等待。。直到子线程执行完毕
10             # 参数6,表示主线程在此最多等待6秒
11
12 print(33)
13 print(33)

未完待续。。。。。。

时间: 2024-10-01 02:20:25

python基础篇【第十篇】多路复用、多线程的相关文章

python运维开发(十)----IO多路复用多线程、进程、协程

内容目录: python作用域 python2.7和python3.5的多继承区别 IO多路复用 多线程.进程.协程 python作用域  python中无块级作用域 if 1 == 1: name = 'jabe' print(name) #可以正常输出jabe #在python中无块级作用域 #在c#或者java中是不能这样使用的,提示name未定义的 python中以函数为作用域 def func(): name = 'jbae' func() print(name) #会提示name为定

Python开发【第二十篇】:缓存

Python开发[第二十篇]:缓存redis&Memcache 点击这里 Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached基于一个存储键/值对的hashmap.其守护进程(daemon )是用C写的,但是客户端可

Python基础学习(十)

Python I/O模型 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 概念说明 在进行解释之前,首先要说明几个概念: 用户空间和内核空间 进程切换 进程的阻塞 文件描述符 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件

Python基础之【第一篇】

Python简介: python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承. Python可以应用于众多领域,如:数据分析.组件集成.网络服务.图像处理.数值计算和科学计算等众多领域.目前业内几乎所有大中型互联网企业都在使 用Python,如:Youtube.Dropbox.BT.Quora(中国知乎).豆瓣.知乎.Google.Yahoo!.Facebook

python全栈开发基础【第二十篇】利用multiprocessing模块开进程

一.multiprocessing模块介绍 python中的多线程无法利用CPU资源(主要指计算密集型任务),在python中大部分情况使用多进程.python中提供了非常好的多进程包multiprocessing. multiprocessing模块用来开启子进程,并在子进程中执行功能(函数),该模块与多线程模块threading的编程接口类似. multiprocessing的功能众多:支持子进程.通信和共享数据.执行不同形式的同步,提供了Process.Queue.Pipe.Lock等组件

Python基础—面向对象(进阶篇)

通过上一篇博客我们已经对面向对象有所了解,下面我们先回顾一下上篇文章介绍的内容: 上篇博客地址:http://www.cnblogs.com/phennry/p/5606718.html 面向对象是一种编程方式,此编程方式的实现是基于对类和对象的使用: 类是一个模版,模板中包装了多个方法供使用(这里方法就是函数): 对象,根据模板创建的实例,实例用于调用被包装在类中的函数: 面向对象的三大特性:封装.继承.多态. 今天博客的内容主要介绍:Python类的成员.成员修饰符.类的特殊成员.异常处理和

Python基础(Django第二篇)

一.Django路由系统 说明:Django中每一个请求的url必须有一个相应的函数来处理,当请求到达时会根据urls.py文件配置的规则从上往下匹配,匹配一条则不再往下匹配. 配置文件:urls.py 配置方式: 静态路由:一个url对应一个views中的函数. 例:url(r'^index/$', views.index), 动态路由:多个URL对应一个views中的函数,此处的url多为正则匹配. 例:url(r'^index/(.*)/$', views.index), 默认路由:当此条

Python之路(第二十篇) subprocess模块

一.subprocess模块 subprocess英文意思:子进程 那什么是进程呢? (一)关于进程的相关理论基础知识 进程是对正在运行程序的一个抽象,进程的概念起源于操作系统,是操作系统最核心的概念,操作系统的其他所有内容都是围绕进程的概念展开的. 所以想要真正了解进程,必须事先了解操作系统. 程序员无法把所有的硬件操作细节都了解到,管理这些硬件并且加以优化使用是非常繁琐的工作,这个繁琐的工作就是操作系统来干的,有了他,程序员就从这些繁琐的工作中解脱了出来,只需要考虑自己的应用软件的编写就可以

Python 基础【第五篇】元组和列表

一 .Python之列表: 其实所谓的列表我个人感觉和shell 中的数组是一样的(只是个人见解哦),列表其实说白了就是元素的组合: 格式: Name = [a,b,c,d] 下标: 每一个列表中的元素都对应一个下标下标的起始位为0 比如列表[a,b,c,d] a对应的下标为0 b对应的下标为1 c对应的下标为2 …… 1.1.定义列表: 比如定义列表group 元素分别为(test,11,bbb,343,ccc) >>> group = ["test",11,&qu

Python开发【第十篇】:CSS (二)

Python开发[前端]:CSS Kylin Zhang 发表于 2016-11-10 13:13:57 css样式选择器 标签上设置style属性: <body> <div style="height: 48px;">第一层</div> <div style="height: 48px;">第二层</div> <div style="height: 48px;">第三层&l