python 程式的使用和理解

夾著巧克力吃發表於2021-01-01

概述

一說程式,很多人就想要問執行緒,那麼就先說下兩者的不同吧

其實程式就是一個個的程式
那執行緒其實是程式裡面的一個個子功能

在舉例子來說明,我們以前在電腦前掛QQ,多個qq其實就是一個不同的程式,程式之間是相互獨立執行的,也就是每一個程式都會消耗一份系統的資源。
那麼執行緒呢,就比如說我們點開qq了,看到裡面的各個功能,有什麼聊天,小程式,發空間等等這些,他們就相當於一個個執行緒,也就是說,其實,程式裡面是包含著執行緒的,並且,執行緒是的資源是共享的。

常用方法

我在工作過程中,主要使用的是程式,那能避免使用執行緒,我還是避免使用的,因為資源的共享,會導致出現很多的問題。

那接下來,我就直接說一下程式的簡單使用吧:
首先在python中使用的庫

from multiprocessing import Process,Manager,pool,Value

一般我是這麼匯入,和用到如下的庫。

那麼現在淺顯的說一下上面的幾個函式的使用方法吧

首先Process,就是啟動一個程式,

p = process(引數)
p.start()

其次,Manager,Value的話,主要是多個程式如果使用同一個區域性變數的話,就需要使用上面這兩個函式
Manager有很多的方法,我主要使用dict和list兩種,當然,如果dicct的話,會有一個坑,就是深層複製,無法複製成功,需要由外層進行引導。

最後pool的話是開始一個程式池,這個的話,其實使用方法大致和Process類似。

python multiprocessing

說明幾點:

  • 首先,在程式裡面是可以在接著開程式的。
    其實程式和執行緒可以搭配著使用,但是這樣就會比較亂。
  • 資源共享需要事先宣告,然後不管你開多少個程式,都是共享的,但是,千萬不要再程式裡面再去申明程式。
  • 資源共享Manager.dict()是有坑在裡面的,現在接下來就說明這個問題

如果需要對dict的深層賦值,我們只能曾淺層開始一步步傳值。
當時這片文章的一個理解,對我幫助特別大:
https://segmentfault.com/a/1190000018619281

我自己也寫了如下程式碼,淺層次,從使用的角度,驗證了一下:


from multiprocessing import Process,Manager

import datetime

class TestMul(object):

    def __init__(self):
        self.balck = Manager().dict()
        self.freeze = Manager().dict()
        self.ips = [
            "192.168.111.7",
            "192.168.111.8",
            "192.168.112.1",
            "192.168.112.2",
        ]


    def forall_sleep(fn):
        def inloop(self,*args):
            for ip in self.ips:
                print ip
                fn(self,ip,*args)
        return inloop


    def chose_dict(self):
        pass


    def decision(self,probelm):
        type_anmorl = {
            "fullblack": self.balck,
            "halfblack": self.freeze,
        }
        return type_anmorl[probelm]

    @forall_sleep
    def ip_write1(self,ip,problem):
        problem_dict,problem_type = self.decision(problem)
        if not problem_dict.has_key(ip):
            self.writ_dict2(problem_dict,ip)
            print problem_dict

        else:
            problem_dict["test"]["time"] +=1
            print problem_dict

        return problem_dict


# 問題的舉例
    def writ_dict1(self,dict_massage,ip):
        dict_massage[ip] = str(datetime.datetime.now())
        dict_massage["test"] = {}
        row = dict_massage["test"]
        row["time"] = 1
        dict_massage["test"] = row
        dict_massage["a"] = {}
        dict_massage["a"]["b"] = str(datetime.datetime.now())
        print dict_massage

    def writ_dict2(self,dict_massage,ip):
        dict_massage[ip] = str(datetime.datetime.now())
        dict_massage["test"] = {}
        row = dict_massage["test"]
        row["time"] = 1
        dict_massage["test"] = row
        dict_massage["a"] = {}
        raw = dict_massage["a"]
        raw["b"] = str(datetime.datetime.now())
        dict_massage["a"] = raw
        print dict_massage




if __name__ == '__main__':
    t = TestMul()
    a = t.decision(probelm = "fullblack")
    # print a
    # t.ip_write1("fullblack")  #這個是一般裝飾器的用法
    t.writ_dict1(a,"192.168.112.2")
    t.writ_dict2(a, "192.168.112.2")

結果如下:

{'test': {'time': 1}, 'a': {}, '192.168.112.2': '2021-01-01 17:18:49.486341'}
{'test': {'time': 1}, 'a': {'b': '2021-01-01 17:18:49.487344'}, '192.168.112.2': '2021-01-01 17:18:49.487202'}

直接看Manager生成的不同的程式碼就可以。

我當時還寫了一個裝飾器,那這裡就額外對裝飾的使用進行一個初步的說明吧。
裝飾器其實就是簡化了我們的一個使用,我上面寫的裝飾器,其實不太正規,但是,可以用來加深對裝飾器的一個理解。
別人的文章會對裝飾器多一個深度的剖析,但是,我們工作中,根本用不到那些東西。只需要把用到的掌握好就可以。

其實裝飾主要是傳引數和不傳引數的,我們主要看最裡面的那層巢狀就好了

    def forall_sleep(fn):
        def inloop(self,*args):
            for ip in self.ips:
                print ip
                fn(self,ip,*args)
        return inloop

首先,說一下*args一般情況呢,我們還可以帶一個**kwargs這裡我沒帶,但我都說一下,一個傳入的是不定長的引數,一個字典型的引數,這兩個呢,其實是對應你原函式的一個引數的。
接下來,要關注的是
fn(self,ip,*args)
t.ip_write1("fullblack")
fn其實是代表,原函式的,後面是他要呼叫的引數,這個是要跟原函式一一對應的。
能知道,我為什麼就傳入一個引數了嗎?原函式可以兩個呢?
這也是我為什麼說,我寫的這個裝飾器不正規的原因。因為他不通用。

@forall_sleep
    def ip_write1(self,ip,problem):
        problem_dict,problem_type = self.decision(problem)
        if not problem_dict.has_key(ip):
            self.writ_dict2(problem_dict,ip)
            print problem_dict

因為這個ip,我放在裝飾器中去了。
關於使用裝飾器,函式是怎麼呼叫的,我推薦大家看我的另一篇文章,當然,也不是我的自賣自誇。
https://blog.csdn.net/weixin_43635231/article/details/110442738

接著說,上面,程式dict的解決辦法,其實就是改成這麼呼叫就可以了

#例子:
def test(idx, test_dict):
    test_dict['test'][idx] = idx

## 正確的使用方式

def test(idx, test_dict):
    row = test_dict['test']
    row[idx] = idx
    test_dict['test'] = row

確實有點麻煩,但是卻又是無可奈何

相關文章