【python測試開發棧】python內存管理機制(一)—引用計數

什麼是內存

在開始進入正題之前,我們先來回憶下,計算機基礎原理的知識,為什麼需要內存。我們都知道計算機的CPU相當於人類的大腦,其運算速度非常的快,而我們平時寫的數據,比如:文檔、代碼等都是存儲在磁盤上的。磁盤的存取速度完全不能匹配cpu的運算速度,因此就需要一个中間層來適配兩者的不對等,內存由此而來,內存的存取速率很快,但是存儲空間不大。

舉一個圖書館的例子,便於大家理解,我們圖書館的書架就相當於磁盤,存放了大量的圖書可以供我們閱讀,但是如果書放在書架上,我們沒辦法直接閱讀(效率低),只能將書取出來,放在書桌上看,那書桌就相當於內存。

內存回收

內存資源畢竟是有限的,所以在使用之後,必須被回收掉,否則系統運行一段時間后就會因無內存可用而癱瘓。我們軟件測試領域常用的兩種語言:java和python,全部都採用內存自動回收的方法,也就是我們只管申請內存,但是不管釋放內存,由jvm和python解釋器來定期觸發內存回收。作為對比,C語言和C++中,程序員需要使用malloc申請內存,使用free去釋放內存,malloc和free必須成對的出現,否則非常容易出現內存問題。

還拿上面圖書館的例子,假如圖書館的書看完之後放在書桌上就可以(因為圖書可自動回收),那麼很快的,就沒有位置給新進來的同學看書了。這時候就需要圖書館管理員(jvm或python解釋器)定期的回收圖書,清空書桌。不過正常情況下,我們離開圖書館時,要自己清空書桌,將書放回書架(類似C語言和C++的內存回收方式)。

python內存管理

引用計數

python通過引用計數來進行內存管理,每一個python對象,都維護了一個指向該對象的引用計數。python的sys庫提供了getrefcount()函數來獲取對象的引用計數。下面我們看個例子(注意:不同版本的python,運行結果不同,我這裏採用的是python3.7.4):

"""
    @author: xuanke
    @time: 2019/11/27
    @function: 測試python內存
"""
import sys

class RefClass(object):
    def __init__(self):
        print("this is init")

def ref_count_test():
    # 驗證普通字符串
    str1 = "abc"
    print(sys.getrefcount(str1))
    # 驗證稍微複雜點的字符串
    print(sys.getrefcount("xuankeTester"))
    # 驗證小的数字
    print(sys.getrefcount(12))
    # 驗證大的数字
    print(sys.getrefcount(257))
    # 驗證類
    a = RefClass()
    print(sys.getrefcount(a))
    # 驗證引用計數增加
    b = a
    print(sys.getrefcount(a))

    # 驗證引用計數減少
    b = None
    print(sys.getrefcount(a))

if __name__ == '__main__':
    ref_count_test()

大家先來思考下,最終的結果會是什麼?!我覺得應該很多人都會答錯,因為不同版本的python,對引用變量個數有影響(主要是可復用的對象)。我們先貼出來運行結果,再來分析產生結果的原因:

27
4
9
3
this is init
2
3
2

不過提前聲明一點:sys.getrefcount函數在使用時,因為將對象(比如上例中的str1)作為參數傳入,所以會額外增加一個變量(相當於getrefcount持有了str1的引用),因此實際每個對象的實際引用計數都得減1。下面分別介紹下上面的幾種情況:

  • 字符串: str1=’abc’的引用數是27-1=26,是因為字符串’abc’比較簡單,在python解釋器(CPython)中確實可能存在26個引用。作為對比,在python2.7中,str1的引用變量個數是3-1=2。而字符串’xuanketester’,是我自定義的一個字符串,所以不可能會有其他額外的引用,所以其引用變量個數是3-1=2(至於為什麼是2,理論應該是0,是因為python解釋器默認持有了所有字符串的兩個引用)。
  • 数字: 数字12對應的引用計數個數是9-1=8,而257對應的引用計數個數是3-1=2,這主要是因為,在python初始化過程中,就創建了從-5到256的数字,緩存起來,這樣做是為了頻繁的分配內存,提高效率。而對於不在這個區間的数字,則會重新分配內存空間。所以数字12因為被複用,其引用計數個數是8(在python2.7.14中,其引用計數個數是8)。
  • 類: 在上面例子中,創建一個RefClass對象,其引用計數就是2-1=1,因為其是一個我們自定義的類對象,在python解釋器(Cpython)中肯定不會被複用。

我們可以通過打印內存地址的方式來驗證上面這幾種情況:

    def memory_address_test():
    str1 = 'xuankeTester'
    str2 = 'xuankeTester'
    print(id(str1))
    print(id(str2))

    str3 = 'abc'
    str4 = 'abc'
    print(id(str3))
    print(id(str4))

    a = 12
    b = 12
    print(id(a))
    print(id(b))

    c = 257
    d = 257
    print(id(c))
    print(id(d))

按照我們上面的分析,c和d的地址應該是不一樣的,a和b的地址是一樣的,字符串str1和str2、str3和str4內存地址都是一樣的。但是我在pycharm中,直接運行py文件,結果卻和預想的不一致,結果如下:

2854496960176
2854496960176
2854496857840
2854496857840
140724423258720
140724423258720
2854498931120
2854498931120

所有情況的內存地址都是一樣的,這是為什麼呢?我考慮到是不是pycharm對py文件做了優化,於是我又在命令行嘗試執行,結果還是一樣的。所以,我猜測可能是python解釋器在執行文件時,為了提高py文件的執行效率,對文件的內存地址做了優化—相同內容的對象內存地址都一樣。

為了驗證這個想法,我直接在python交互模式下執行,果然得到了我想要的結果:

Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a=12
>>> b=12
>>> id(a)
140724423258720
>>> id(b)
140724423258720
>>> a=257
>>> b=257
>>> id(a)
2559155778384
>>> id(b)
2559155778192
>>> a='xuankeTester'
>>> b='xuankeTester'
>>> id(a)
2559155711280
>>> id(b)
2559155711280
>>>

從上面可以看到兩個257對應的地址確實是不一樣的,和我們最初判斷的是一致的。

總結

python通過對象的引用計數來管理內存,其實java的JVM也有用引用計數,所以理解了引用計數,為我們理解python的垃圾回收方法打下了基礎。本計劃這一篇文章就將python內存管理的機制講完的,但是發現一個內存引用計數就有很多東西得寫,所以索性就分兩篇文章來寫,之後再寫一篇文章來介紹python的垃圾回收方式。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

3c收購,鏡頭 收購有可能以全新價回收嗎?

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

賣IPHONE,iPhone回收,舊換新!教你怎麼賣才划算?

.NET Core 3.0 使用Nswag生成Api文檔和客戶端代碼

摘要

在前後端分離、Restful API盛行的年代,完美的接口文檔,成了交流的紐帶。在項目中引入Swagger (也稱為OpenAPI),是種不錯的選擇,它可以讓接口數據可視化。下文將會演示

  • 利用Nswag如何生成Api文檔

  • 利用NSwagStudio如何生成客戶端代碼,並且進行測試

什麼是 Swagger/OpenAPI?

Swagger 是一個與語言無關的規範,用於描述 REST API。Swagger 項目已捐贈給 OpenAPI 計劃,現在它被稱為開放 API。這兩個名稱可互換使用,但 OpenAPI 是首選。它允許計算機和人員了解服務的功能,而無需直接訪問實現(源代碼、網絡訪問、文檔)。其中一個目標是盡量減少連接取消關聯的服務所需的工作量。另一個目標是減少準確記錄服務所需的時間。

Nswag VS Swashbuckle?

.NET Swagger 實現類庫有兩個比較流行:

  • Swashbuckle.AspNetCore 是一個開源項目,用於生成 ASP.NET Core Web API 的 Swagger 文檔。

  • NSwag 是另一個用於生成 Swagger 文檔並將 Swagger UI 或 ReDoc 集成到 ASP.NET Core Web API 中的開源項目。此外,NSwag 還提供了為 API 生成 C# 和 TypeScript 客戶端代碼的方法。

 

為什麼我在.NET core3.0中選擇NSwag呢,NSwag比較活躍,一直在更新,功能也很強大,可以完美的代替Swashbuckle.AspNetCore具體可以參考:https://github.com/aspnet/AspNetCore.Docs/issues/4258

一、利用Nswag生成Api文檔

步驟
  1. 創建Asp.NET Core Api項目,並且集成NSwag

  2. 配置項目

  3. 運行項目

創建Asp.NET Core Api項目,並且集成NSwag

我們將簡單的創建一個ASP.NET core API項目。將其命名為“WebAPIwithSwg”。基於.NETcore3.0

安裝nuget包NSwag.AspNetCore

接下來,在Startup.cs文件中配置Nswag服務和中間件。

在ConfigureServices方法中添加服務

  public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddSwaggerDocument(); //註冊Swagger 服務
        }
在Configure方法中添加Nswag中間件
 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
            app.UseOpenApi(); //添加swagger生成api文檔(默認路由文檔 /swagger/v1/swagger.json)
            app.UseSwaggerUi3();//添加Swagger UI到請求管道中(默認路由: /swagger).
        }
配置項目

運行項目

右鍵項目在瀏覽器中查看,查看swagger UI需要在url後面添加“/swagger”。本示例http://localhost:54117/swagger

二、利用NSwagStudio如何生成客戶端代碼,並且進行測試
提供GUI界面是NSwag的一大特點,只需要下載安裝NSwagStudio,即可生成客戶端代碼。
步驟
  1. 現在安裝NSwagStudio

  2. NSwagStudio配置,生成客戶端代碼

  3. 創建測試客戶端項目

下載安裝NSwagStudio

下載NSwag Studio http://rsuter.com/Projects/NSwagStudio/installer.php 安裝之後打開 NSwag Studio 如圖

NSwagStudio配置,生成客戶端代碼

選擇runtime,我選擇的是NETCore30,切換OpenAPI/Swagger Specification ,在Specification UR輸入你的Swagger.json路徑,本示例:http://localhost:54117/swagger/v1/swagger.json輸入路徑之後,點擊 create local copy 按鈕獲取json。

接下配置來生成客戶端代碼。我們首先選擇csharp client”複選框,然後勾選掉 “Inject Http Client via Constructor (life cycle is managed by caller)” ,最後設置下輸出路徑 點擊生成文件(Generate Files)。步驟如下

到此客戶端代碼已經自動生成。

查看生成的部分代碼


public async System.Threading.Tasks.Task<System.Collections.Generic.ICollection<WeatherForecast>> GetAsync(System.Threading.CancellationToken cancellationToken)
        {
            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/WeatherForecast");
    
            var client_ = new System.Net.Http.HttpClient();
            try
            {
                using (var request_ = new System.Net.Http.HttpRequestMessage())
                {
                    request_.Method = new System.Net.Http.HttpMethod("GET");
                    request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
    
                    PrepareRequest(client_, request_, urlBuilder_);
                    var url_ = urlBuilder_.ToString();
                    request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
                    PrepareRequest(client_, request_, url_);
    
                    var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
                    try
                    {
                        var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
                        if (response_.Content != null && response_.Content.Headers != null)
                        {
                            foreach (var item_ in response_.Content.Headers)
                                headers_[item_.Key] = item_.Value;
                        }
    
                        ProcessResponse(client_, response_);
    
                        var status_ = ((int)response_.StatusCode).ToString();
                        if (status_ == "200") 
                        {
                            var objectResponse_ = await ReadObjectResponseAsync<System.Collections.Generic.ICollection<WeatherForecast>>(response_, headers_).ConfigureAwait(false);
                            return objectResponse_.Object;
                        }
                        else
                        if (status_ != "200" && status_ != "204")
                        {
                            var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); 
                            throw new ApiException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null);
                        }
            
                        return default(System.Collections.Generic.ICollection<WeatherForecast>);
                    }
                    finally
                    {
                        if (response_ != null)
                            response_.Dispose();
                    }
                }
            }
            finally
            {
                if (client_ != null)
                    client_.Dispose();
            }
        }
創建測試客戶端項目

創建一個控製程序項目,命名“WebApiClient”。

把自動生成的類“WeatherForecastClient”添加到客戶端項目中,然後安裝Newtonsoft

最後在Main函數中添加測試代碼,開始使用Api。

 static async System.Threading.Tasks.Task Main(string[] args)
        {

            var weatherForecastClient = new WeatherForecastClient();
            //gets all values from the API
            var allValues = await weatherForecastClient.GetAsync();
            Console.WriteLine("Hello World!");
        }

運行客戶端應用程序,進行調用api

當然如果需要調試api項目內部代碼,可以設置斷點,進入一步一步的調試

小結:NSwag 功能遠不止這些,本篇文章演示了如何生成api文檔和自動生成的api客戶端代碼方便我們調試,也可以作為對應的sdk。

參考:微軟官方文檔—https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-nswag?view=aspnetcore-2.2&tabs=visual-studio

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※公開收購3c價格,不怕被賤賣!

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

JavaScript 是否應該重命名

  在誕生 25 年之後,JavaScript 語言仍然讓很多人困惑不已。所以一個老生常談的問題是:它是否應該重命名?呼籲改名的支持者列舉了一系列理由,包括:

  • JavaScript 本意指的是 ECMAScript 的子集,但使用中它經常被指代多種不同的 ECMAScript 超集
  • JavaScript 是甲骨文公司的商標,這與 JavaScript 作為 Web 平台核心組件的身份不相符合,Web 平台是建立在開放技術和標準基礎上的
  • JavaScript 連官方 logo 都沒有
  • JavaScript 與 Java 沒有一點關係,幾十年來它給非技術人員造成了混淆。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

3c收購,鏡頭 收購有可能以全新價回收嗎?

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

賣IPHONE,iPhone回收,舊換新!教你怎麼賣才划算?

雅虎日本在其餐廳徵收“油炸食品稅”

  為了推廣健康生活方式,減少僱員中間的肥胖率,雅虎日本在其總部餐廳開始徵收“油炸食品稅”。從 10 月 8 日開始,炸豬排之類的油炸食品價格上漲,而水煮魚或烤魚之類的魚類食品則價格下降。

  它在 2017 年的體檢显示,45% 的僱員 LDL 膽固醇含量較高。它的自助餐廳每天有 1000 名僱員吃飯,油炸食品要比水煮魚或烤魚受歡迎得多。除了炸豬排漲價外,炸雞排也漲了 100 日元至 691 日元。如今到了午餐點,魚類食品一售而空,官員表示效果顯著。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※公開收購3c價格,不怕被賤賣!

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

傳谷歌母公司欲收購Fitbit 擬推自有品牌可穿戴設備

  原標題:Google is reportedly trying to buy Fitbit

  網易科技訊,10 月 29 日消息,據外媒報道,據知情人士透露,谷歌母公司 Alphabet 正在就收購美國可穿戴設備公司 Fitbit 與後者進行談判。不過,目前兩家公司還沒有確認這筆交易,也不清楚 Alphabet 的報價。上個月,有報道稱 Fitbit 正在探索出售的可能。

  多年來,谷歌憑藉其 Wear OS 操作系統在可穿戴市場上佔據了重要地位,但它始終難以與 Apple Watch 競爭,儘管其得到了包括 LG、Fossil 和 TicWatch 在內的眾多公司支持。就連主要的安卓製造商三星也未使用 Wear OS,而是使用自己的 Tizen 操作系統。

  今年 1 月,谷歌斥資 4000 萬美元從 Fossil 手中收購了某種智能手錶技術,但目前尚不清楚該技術到底是什麼,Fossil 高管將其描述為“尚未投放市場的新產品創新”,不過迄今仍然沒有上市。

  多年來,始終有傳言稱谷歌希望推出自家品牌的 Pixel 智能手錶。在 2016 年的某個時候,這些計劃幾乎促使谷歌品牌的智能手錶上市,但該公司最終擱置了計劃,因為其擔心這些手錶可能“傷及谷歌硬件品牌的聲譽”。這些 LG 製造的智能手錶後來在 2017 年以 LG Watch Sports 和 LG Watch Style 的形式發布,評價一般。

  從那時起,谷歌打造自家硬件野心開始膨脹。2017 年,谷歌收購了 HTC 智能手機工程團隊以開發 Pixel 手機,而 Fitbit 的收購可能會幫助其在可穿戴設備領域取得類似的進展。

  與此同時,蘋果在 Apple Watch 上的經驗表明,健康正迅速成為智能手錶的殺手級應用,這也是 Fitbit 自身健身追蹤器越來越關注的一個領域。然而,儘管 Fitbit 在 2016 年收購了智能手錶製造商 Pebble,但其在智能手錶方面的表現卻不盡如人意。例如,今年早些時候發布的健身跟蹤器 Fitbit Versa 2,其實本質上就是一款普通的智能手錶。

  谷歌和 Fitbit 拒絕就上述報道置評。(小小)

  

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※公開收購3c價格,不怕被賤賣!

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享