python进程

python进程-进程的执行顺序是计算机的调度算法决定的

python进程

  • 创建子进程-fork

    import os
    
    import time
    
    
    ret = os.fork()   #os.fork 会创建一个子进程 把父进程赋值给ret 父进程大于0 然后把子进程赋值给ret等于0
    
    if ret == 0:
    
        while True:#子进程执行
            print("----1----")
            time.sleep(1)
    
    else:
    
        while True:#父进程执行
            print("----2----")
            time.sleep(1)
    
    
    #父进程创建了子进程   但不一定父进程就会先执行   跟局操作系统的调度算法  决定
    
    # 运行结果
    ----2----
    ----1----
    ----1----
    ----2----
    ----2----
    ----1----
    ----2----
    ----1----
    ----1----
    ----2----
    死循环
    
  • fork的返回值-getpid-getppid

    import os
    
    ret = os.fork()  #从这句话开始  下面的代码父子进程都执行
    print(ret)
    if ret>0:
        print("----父进程--%d--"%os.getpid()) #父进程中fork的返回值,就是刚刚创建出来的子进程的id
        #os.getpid()是父进程的PID 用ps -aux 查看就只到了
    else:
        print("----子进程--%d-%d-"%(os.getpid(),os.getppid()))
        #os.getpid()是子进程PID,os.getppid()是父进程的PID
    
    # 运行结果
    1635
    ----父进程--1634--
    0
    ----子进程--1635-1634-
    
  • 先退出

    import os
    import time
    
    ret = os.fork()
    
    if ret == 0:
        print("----子进程----")
        time.sleep(5)
        print("----子进程over----",end="")
    else:
        print("----父进程----")
        time.sleep(3)
    
    print("----over----")
    
    #主进程(父进程)结束,那么终端直接给提示  不会因为你的子进程没有结束而等它
    #但是也不会因为你的主进程结束而结束子进程
    
    # 运行结果
    ----父进程----
    ----子进程----
    ----over----
    zhangshengxiaodeMacBook-Air:01.进程程序 xiaoge$ ----子进程over--------over----
    
  • 修改全局变量

    import os
    import time
    
    g_num = 100                 
    
    ret = os.fork() #每一个进程都是个单独不共享的  所以这里子进程把全局变量改了
    #主进程的全局变量没变
    
    #所以这里的所有内容都不共享 每个进程都有个这份内容  不管那个进程修改了里面
    #的内容都不影响其他的进程内容
    
    if ret == 0:
        print("----process-1----")
        g_num += 1
        print("----process-1 g_num = %d"%g_num)
    else:
        time.sleep(3)
        print("----process-2----")
        print("----process-2 g_num = %d"%g_num)
    
    # 运行结果
    ----process-1----
    ----process-1 g_num = 101
    ----process-2----
    ----process-2 g_num = 100
    
  • 多次fork-1

    import os
    
    #父进程
    ret = os.fork()
    
    if ret == 0:
        #子进程
        print("----1----")
    else:
        #父进程
        print("----2----")
    
    
    #父子进程    
    ret = os.fork()
    
    if ret == 0:
        #孙子
        #2儿子
        print("----11----")
    else:
        #儿子
        #父进程
        print("----22----")
    
    # 运行结果
    ----2----
    ----22----
    ----1----
    ----11----
    ----22----
    ----11----
    
  • 多次fork-2

    import os
    
    #父进程
    ret = os.fork()
    
    if ret == 0:
        #子进程
        print("----1----")
    else:
        #父进程
        print("----2----")
    
    
        ret = os.fork()
    
        if ret == 0:
            #2儿子
            print("----11----")
        else:
            #父进程
            print("----22----")
    
    # 运行结果
    ----2----
    ----22----
    ----1----
    ----11----
    
  • 3-fork

    import os
    
    os.fork()
    os.fork()
    os.fork()
    
    """
    #下面是fork炸弹,不相信你可以执行下看看
    while True:
        os.fork()
    """
    
    print("----1----")
    
    # 运行结果
    ----1----
    ----1----
    ----1----
    ----1----
    ----1----
    ----1----
    ----1----
    ----1----
    
  • Process创建进程

    from multiprocessing import Process  #Process  是个类
    import time
    
    def test():
        while True:
            print("----test----")
            time.sleep(1)
    
    p = Process(target=test) #target指向谁  这个进程就执行谁
    p.start() #让这个进程开始执行test函数里的代码
    
    
    while True:
        print("----main----")
        time.sleep(1)
    
    # 运行结果
    ----main----
    ----test----
    ----test----
    ----main----
    ----test----
    ----main----
    ----test----
    ----main----
    ----test----
    ----main----
    死循环
    
  • Process创建的子进程和主进程的结束

    from multiprocessing import Process  #Process  是个类
    import time
    
    def test():
        for i in range(5):
            print("----test----")
            time.sleep(1)
    
    p = Process(target=test) #target指向谁  这个进程就执行谁
    p.start() #让这个进程开始执行test函数里的代码
    
    # 所有子进程结束后  主进程才结束  这就是和fork的区别
    
    # 运行结果
    ----test----
    ----test----
    ----test----
    ----test----
    ----test----
    
  • join子进程

    from multiprocessing import Process
    import random
    import time
    
    def test():
        for i in range(random.randint(1,5)):
            print("----%d----"%i)
            time.sleep(1)
    
    p = Process(target=test)
    
    p.start()
    
    #等待p.start() 进程执行完
    p.join()#堵塞(等待子进程执行完了 在执行主进程)
    #在join()这个括号里写1就是等待子进程1秒 看你写几就等待几秒
    
    print("----main----")
    
    # 运行结果
    ----0----
    ----main----
    
  • Process子类创建进程

    from multiprocessing import Process
    import time
    
    class MyNewProcess(Process):
    
        def run(self):   #从写父类的run方法 父类里的run方法是个接口
            while True:
                print("----1----")
                time.sleep(1)
    
    p = MyNewProcess()
    p.start()
    
    while True:
        print("----main----")
        time.sleep(1)
    
    # 运行结果
    ----main----
    ----1----
    ----main----
    ----1----
    ----1----
    ----main----
    ----1----
    ----main----
    ----1----
    ----main----
    ----1----
    ----main----
    ----1----
    ----main----
    死循环
    
  • Process类的run方法

    from multiprocessing import Process
    import time
    
    class MyNewProcess(Process):
        pass
    
    p = MyNewProcess()
    p.start() #父类里 的run方法只是个接口 你可以在子类里从写run方法
    
    while True:
        print("----main----")
        time.sleep(1)
    
    # 运行结果
    ----main----
    ----main----
    ----main----
    ----main----
    ----main----
    ----main----
    ----main----
    死循环
    
  • Process子类创建完整版

    #创建新的进程还能够使用类的方式,可以自定义一个类,继承Process类,每次实例化这个类的时候,就等同于实例化一个进程对象,请看下面的实例:
    from multiprocessing import Process
    import time
    import os
    
    #继承Process类
    class Process_Class(Process):
        #因为Process类本身也有__init__方法,这个子类相当于重写了这个方法,
        #但这样就会带来一个问题,我们并没有完全的初始化一个Process类,所以就不能使用从这个类继承的一些方法和属性,
        #最好的方法就是将继承类本身传递给Process.__init__方法,完成这些初始化操作
        def __init__(self,interval):
            Process.__init__(self)
            self.interval = interval
    
        #重写了Process类的run()方法
        def run(self):
            print("子进程(%s) 开始执行,父进程为(%s)"%(os.getpid(),os.getppid()))
            t_start = time.time()
            time.sleep(self.interval)
            t_stop = time.time()
            print("(%s)执行结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start))
    
    if __name__=="__main__":
        t_start = time.time()
        print("当前程序进程(%s)"%os.getpid())        
        p1 = Process_Class(2)
        #对一个不包含target属性的Process类执行start()方法,就会运行这个类中的run()方法,所以这里会执行p1.run()
        p1.start()
        p1.join()
        t_stop = time.time()
        print("(%s)执行结束,耗时%0.2f"%(os.getpid(),t_stop-t_start))
        
    # 运行结果
    当前程序进程(1783)
    子进程(1784) 开始执行,父进程为(1783(1784)执行结束,耗时2.00(1783)执行结束,耗时2.01
    
  • 进程池Pool

    #初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行,请看下面的实例:
    from multiprocessing import Pool
    import os,time,random
    
    def worker(msg):
        t_start = time.time()
        print("%s开始执行,进程号为%d"%(msg,os.getpid()))
        #random.random()随机生成0~1之间的浮点数
        time.sleep(random.random()*2) 
        t_stop = time.time()
        print(msg,"执行完毕,耗时%0.2f"%(t_stop-t_start))
    
    po=Pool(3) #定义一个进程池,最大进程数3
    for i in range(0,10):
        #Pool.apply_async(要调用的目标,(传递给目标的参数元祖,))
        #每次循环将会用空闲出来的子进程去调用目标
        po.apply_async(worker,(i,))
    
    print("----start----")
    po.close() #关闭进程池,关闭后po不再接收新的请求
    po.join() #等待po中所有子进程执行完成,必须放在close语句之后
    print("-----end-----")
    
    # 运行结果
    ----start----
    0开始执行,进程号为1797
    1开始执行,进程号为1798
    2开始执行,进程号为1799
    1 执行完毕,耗时0.33
    3开始执行,进程号为1798
    3 执行完毕,耗时0.23
    4开始执行,进程号为1798
    2 执行完毕,耗时0.76
    5开始执行,进程号为1799
    0 执行完毕,耗时0.95
    6开始执行,进程号为1797
    6 执行完毕,耗时0.08
    7开始执行,进程号为1797
    5 执行完毕,耗时0.48
    8开始执行,进程号为1799
    8 执行完毕,耗时0.33
    9开始执行,进程号为1799
    4 执行完毕,耗时1.15
    9 执行完毕,耗时0.69
    7 执行完毕,耗时1.87
    -----end-----
    
  • 进程池-apply_async

    from multiprocessing import Pool
    import os
    import time
    
    def worker(num):
        for i in range(5):
            print("===pid=%d==num=%d="%(os.getpid(),num))
            time.sleep(1)
    
    #3表示 进程池中最多有3个进程一起执行
    pool = Pool(3) #这个池子最多一次完成3个任务
    
    for i in range(10):
    # print("----%d----"%i)
    # time.sleep(1)
        #向进程池中添加任务
        #注意:如果添加的任务数量超过了  进程池中进程的个数的话,那么不会导致添加不进入
        #   添加到进程中的任务  如果还没有被执行的话,那么此时  他们会等待进程池中的
        #   进程完成一个任务之后,会自动的去用刚刚的那个进程  完成当前的任务
        pool.apply_async(worker,(i,)) #传参数 必须是元组
        #apply_async 这是一个非堵塞方式(不用等,直接添加到进程池满为止)
    
    pool.close() #关闭进程池,相当于  不能再次添加新任务了
    
    pool.join()#主进程  创建/添加  任务后,主进程  默认不会等待进程池中的任务执行玩后才结束
               #而是  当主进程的任务做完之后  立马结束,,,,如果这个地方没join,会导致进程池中
               #的任务不会执行
    
    # 运行结果
    ===pid=1808==num=0=
    ===pid=1809==num=1=
    ===pid=1810==num=2=
    ===pid=1808==num=0=
    ===pid=1809==num=1=
    ===pid=1810==num=2=
    ===pid=1809==num=1=
    ===pid=1808==num=0=
    ===pid=1810==num=2=
    ===pid=1810==num=2=
    ===pid=1809==num=1=
    ===pid=1808==num=0=
    ===pid=1808==num=0=
    ===pid=1810==num=2=
    ===pid=1809==num=1=
    ===pid=1808==num=3=
    ===pid=1810==num=4=
    ===pid=1809==num=5=
    ===pid=1808==num=3=
    ===pid=1810==num=4=
    ===pid=1809==num=5=
    ===pid=1810==num=4=
    ===pid=1809==num=5=
    ===pid=1808==num=3=
    ===pid=1810==num=4=
    ===pid=1808==num=3=
    ===pid=1809==num=5=
    ===pid=1809==num=5=
    ===pid=1808==num=3=
    ===pid=1810==num=4=
    ===pid=1809==num=6=
    ===pid=1810==num=7=
    ===pid=1808==num=8=
    ===pid=1809==num=6=
    ===pid=1810==num=7=
    ===pid=1808==num=8=
    ===pid=1808==num=8=
    ===pid=1810==num=7=
    ===pid=1809==num=6=
    ===pid=1809==num=6=
    ===pid=1808==num=8=
    ===pid=1810==num=7=
    ===pid=1808==num=8=
    ===pid=1810==num=7=
    ===pid=1809==num=6=
    ===pid=1808==num=9=
    ===pid=1808==num=9=
    ===pid=1808==num=9=
    ===pid=1808==num=9=
    ===pid=1808==num=9=
    
  • 进程池-apply

    from multiprocessing import Pool
    import os
    import time
    
    def worker(num):
        for i in range(5):
            print("===pid=%d==num=%d="%(os.getpid(),num))
            time.sleep(1)
    
    #3表示 进程池中最多有3个进程一起执行
    pool = Pool(3) #这个池子最多一次完成3个任务
    
    for i in range(10):
        print("----%d----"%i)
        pool.apply(worker,(i,)) #传参数 必须是元组
        #apply 这是一个堵塞方式(主进程运行到这不动了,等待子进程的任务完成,在运行一个子任务)
    
    pool.close() #关闭进程池,相当于  不能再次添加新任务了
    
    pool.join()#主进程  创建/添加  任务后,主进程  默认不会等待进程池中的任务执行玩后才结束
               #而是  当主进程的任务做完之后  立马结束,,,,如果这个地方没join,会导致进程池中
               #的任务不会执行
    
    # 运行结果
    ----0----
    ===pid=1823==num=0=
    ===pid=1823==num=0=
    ===pid=1823==num=0=
    ===pid=1823==num=0=
    ===pid=1823==num=0=
    ----1----
    ===pid=1824==num=1=
    ===pid=1824==num=1=
    ===pid=1824==num=1=
    ===pid=1824==num=1=
    ===pid=1824==num=1=
    ----2----
    ===pid=1825==num=2=
    ===pid=1825==num=2=
    ===pid=1825==num=2=
    ===pid=1825==num=2=
    ===pid=1825==num=2=
    ----3----
    ===pid=1823==num=3=
    ===pid=1823==num=3=
    ===pid=1823==num=3=
    ===pid=1823==num=3=
    ===pid=1823==num=3=
    ----4----
    ===pid=1824==num=4=
    ===pid=1824==num=4=
    ===pid=1824==num=4=
    ===pid=1824==num=4=
    ===pid=1824==num=4=
    ----5----
    ===pid=1825==num=5=
    ===pid=1825==num=5=
    ===pid=1825==num=5=
    ===pid=1825==num=5=
    ===pid=1825==num=5=
    ----6----
    ===pid=1823==num=6=
    ===pid=1823==num=6=
    ===pid=1823==num=6=
    ===pid=1823==num=6=
    ===pid=1823==num=6=
    ----7----
    ===pid=1824==num=7=
    ===pid=1824==num=7=
    ===pid=1824==num=7=
    ===pid=1824==num=7=
    ===pid=1824==num=7=
    ----8----
    ===pid=1825==num=8=
    ===pid=1825==num=8=
    ===pid=1825==num=8=
    ===pid=1825==num=8=
    ===pid=1825==num=8=
    ----9----
    ===pid=1823==num=9=
    ===pid=1823==num=9=
    ===pid=1823==num=9=
    ===pid=1823==num=9=
    ===pid=1823==num=9=
    
  • 进程间通信-Queue的使用

    #可以使用multiprocessing模块的Queue实现多进程之间的数据传递,Queue本身是一个消息列队程序,首先用一个小实例来演示一下Queue的工作原理:
    
    
    #coding=utf-8
    from multiprocessing import Queue
    q=Queue(3) #初始化一个Queue对象,最多可接收三条put消息
    q.put("消息1") 
    q.put("消息2")
    print(q.full())  #False
    q.put("消息3")
    print(q.full()) #True
    
    #因为消息列队已满下面的try都会抛出异常,第一个try会等待2秒后再抛出异常,第二个Try会立刻抛出异常
    try:
        q.put("消息4",True,2)
    except:
        print("消息列队已满,现有消息数量:%s"%q.qsize())
    
    try:
        q.put_nowait("消息4")
    except:
        print("消息列队已满,现有消息数量:%s"%q.qsize())
    
    #推荐的方式,先判断消息列队是否已满,再写入
    if not q.full():
        q.put_nowait("消息4")
    
    #读取消息时,先判断消息列队是否为空,再读取
    if not q.empty():
        for i in range(q.qsize()):
            print(q.get_nowait())
            
            
    # 运行结果
    False
    True
    消息列队已满,现有消息数量:3
    消息列队已满,现有消息数量:3
    消息1
    消息2
    消息3
    
  • 进程间通信-Queue的实列

    from multiprocessing import Process, Queue
    import os, time, random
    
    # 写数据进程执行的代码:
    def write(q):
        for value in ['A', 'B', 'C']:
            print('Put %s to queue...'%value)
            q.put(value)
            time.sleep(random.random())
    
    # 读数据进程执行的代码:
    def read(q):
        while True:
            if not q.empty():
                value = q.get(True)
                print('Get %s from queue.'%value)
                time.sleep(random.random())
            else:
                break
    
    if __name__=='__main__':
        # 父进程创建Queue,并传给各个子进程:
        q = Queue()
        pw = Process(target=write, args=(q,))
        pr = Process(target=read, args=(q,))
        # 启动子进程pw,写入:
        pw.start()    
        # 等待pw结束:
        pw.join()
        # 启动子进程pr,读取:
        pr.start()
        pr.join()
        # pr进程里是死循环,无法等待其结束,只能强行终止:
        print('')
        print('所有数据都写入并且读完')
    
    # 运行结果
    Put A to queue...
    Put B to queue...
    Put C to queue...
    Get A from queue.
    Get B from queue.
    Get C from queue.
    
    所有数据都写入并且读完
    
  • 进程间通信-进程池中的Queue

    #coding=utf-8
    
    #修改import中的Queue为Manager
    from multiprocessing import Manager,Pool
    import os,time,random
    
    def reader(q):
        print("reader启动(%s),父进程为(%s)"%(os.getpid(),os.getppid()))
        for i in range(q.qsize()):
            print("reader从Queue获取到消息:%s"%q.get(True))
    
    def writer(q):
        print("writer启动(%s),父进程为(%s)"%(os.getpid(),os.getppid()))
        for i in "dongGe":
            q.put(i)
    
    if __name__=="__main__":
        print("(%s) start"%os.getpid())
        q=Manager().Queue() #使用Manager中的Queue来初始化
        po=Pool()
        #使用阻塞模式创建进程,这样就不需要在reader中使用死循环了,可以让writer完全执行完成后,再用reader去读取
        po.apply(writer,(q,))
        po.apply(reader,(q,))
        po.close()
        po.join()
        print("(%s) End"%os.getpid())
        
    # 运行结果
    (2105) start
    writer启动(2107),父进程为(2105)
    reader启动(2109),父进程为(2105)
    reader从Queue获取到消息:d
    reader从Queue获取到消息:o
    reader从Queue获取到消息:n
    reader从Queue获取到消息:g
    reader从Queue获取到消息:G
    reader从Queue获取到消息:e
    (2105) End
    
  • 多种创建进程的方法比较

    ret = os.fork()
    if ret == 0:
        #子进程
    else:
        #父进程
    #这个建议别用 因为它只支持 Mac Linux Uiux
    
    
    p1 = Process(target=xxx)
    p1.start()
    #父子进程都可以完成任务
    
    
    pool = Pool(3)
    pool.apply_async(xxx)
    #主进程用来等待 , , , , 真正的任务都在子进程中执行
    
  • Process类的方法

                    Process语法结构如下
    Process([group[,target[,name,[,args[,kwargs]]]]])
    
    1. target:表示这个进程实列所调用的对象
    
    2. args:表示调用对象的位置参数元组
    
    3. kwargs:表示调用对象的关键字参数字典
    
    4. name:为当前进程实列的别名
    
    5. group:大多数情况下用不到
    
    
                    Process常用方法
    
    1. is_alive():判断进程实列是否还在执行
    
    2. join([timeout]):是否等待进程实列执行结束,或等待多少秒
    
    3. start():启动进程实列(创建子进程)
    
    4. run():如果没有给定target参数,对这个对象调用start()方法时.就将执行对象中的run()方法
    
    5. terminate():不管任务是否完成,立即终止
    
    
                    Process常用属性
    
    1. name:当前进程实列别名,默认为Process-N,N为从1开始递增的整数
    
    2. pid:当前进程实列的PID值
    
  • Queue说明

    初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头);
    
    
    
    Queue.qsize():返回当前队列包含的消息数量;
    
    Queue.empty():如果队列为空,返回True,反之False ;
    
    Queue.full():如果队列满了,返回True,反之False;
    
    Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常;
    
    2)如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常;
    
    Queue.get_nowait():相当Queue.get(False);
    
    Queue.put(item,[block[, timeout]]):将item消息写入队列,block默认值为True1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常;
    
    2)如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常;
    
    Queue.put_nowait(item):相当Queue.put(item, False)
    

多进程拷贝文件

  • copyFile

    from multiprocessing import Pool,Manager
    import os
    
    def copyFileTask(fileName,oldFolderName,newFolderName,queue):
        """完成拷贝一个文件的功能"""
        fr = open(oldFolderName+"/"+fileName)   
        fw = open(newFolderName+"/"+fileName,"w")
    
        content = fr.read()
        fw.write(content)
    
        fr.close()
        fw.close()
    
        queue.put(fileName) 
    
    def main():
        #0.获取用户要copy的文件夹的名字
        oldFolderName = input("请输入原文件夹的名字:")
    
        #1.创建一个文件夹
        newFolderName = oldFolderName+"-复件"
        #print(newFolderName)
        os.mkdir(newFolderName)
    
        #2.获取old的文件夹中的所有的文件名字
        fileNames = os.listdir(oldFolderName)
        #print(fileNames)
    
        #3.使用多进程的方式copy原文件中的所有文件到新的文件夹中
        pool = Pool(5)
        queue = Manager().Queue()
        
        for name in fileNames:
            pool.apply_async(copyFileTask,args=(name,oldFolderName,newFolderName,queue))
    
        num = 0
        allNum = len(fileNames)
        while True:
            queue.get()
            num += 1
            copyRate = num/allNum
            print("\rcopy的进度是:%.2f%%"%(copyRate*100),end="")
            if num == allNum:
                break
    
        print("\n已完成copy.....")
    
        pool.close()
        pool.join()
    
    if __name__ == "__main__":
        main()
    

    僵尸进程:子进程死了父进程没给它收尸
    孤儿进程:父进程死了子进程还是活的,这个孤儿进程是操作系统的pid为1的那个进程给它收尸的

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值