python 調試大法

来源:https://www.cnblogs.com/djdjdj123/archive/2019/12/07/12003426.html
-Advertisement-
Play Games

說在前面 我覺得沒有什麼錯誤是調試器無法解決的,如果沒有,那我再說一遍,如果有,那當我沒說 一、拋出異常 可以通過 raise 語句拋出異常,使程式在我們已經知道的缺陷處停下,併進入到 except 語句 raise句法: raise關鍵字 調用的異常函數名 ValueError (這個函數必須是異 ...


說在前面

我覺得沒有什麼錯誤是調試器無法解決的,如果沒有,那我再說一遍,如果有,那當我沒說

一、拋出異常

可以通過 raise 語句拋出異常,使程式在我們已經知道的缺陷處停下,併進入到 except 語句
 

raise句法:

raise關鍵字

調用的異常函數名 ValueError (這個函數必須是異常類或一個實例)

傳遞給 ValueError 的字元串,包含有用的出錯信息

>>> raise ValueError('This is a error message')
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    raise ValueError('This is a error message')
ValueError: This is a error message

然後使用 try...except 語句來對拋出的異常做處理

通常我們在函數本身中拋出異常,然後在調用該函數的地方使用 try...except 語句處理異常

#定義一個簡單的int類型的加法器
def calculator(num1,num2):
    if isintance(num1,int)and isintance(num2,int):
        raise Exception('Symbol must be a int type number.')
    return num1+num2
 
print('please enter two number:')
num1=input()
num2=input()
#在調用函數的地方使用try語句
try:
    print(calculator(num1,num2))
except Exception as err:
    print('發生了一個錯誤:'+str(err))
#另一種使用情況
try:
            print(key)
            return self[key]
        except KeyError:#如果在上面遇見了keyError
            raise AttributeError(r"'%s' don't have attribute '%s'"%#就拋出這個AttributeError類型的錯誤,順序別弄錯<br>(self.__class__.name,key))

註意上面的 as 語句取得 str ,如果不取也是可以的
  
運行示例:

RESTART: C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/boxPrint.py 
please enter two number:
s
發生了一個錯誤:name 'isintance' is not defined
>>>

二、取的反向跟蹤的字元串

當程式運行出現錯誤時,python會生成一些錯誤信息,這些錯誤信息被稱為“反向跟蹤”,它包含了出錯信息、導致該錯誤的代碼行號,和導致 該錯誤的函數調用 的 序列,這個序列被稱為調用棧。

只要拋出的異常沒有被處理,python就會顯示反向跟蹤

以下麵程式來展示我們對反向跟蹤的解讀

def spam():
    bacon()
def bacon():
    raise Exception('This is the error message')
 
spam()

這就是反向跟蹤:

Traceback (most recent call last):
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/errorExample.py", line 6, in <module>
    spam()
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/errorExample.py", line 2, in spam
    bacon()
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/errorExample.py", line 4, in bacon
    raise Exception('This is the error message')
Exception: This is the error message

我們應該從下往上閱讀方向跟蹤,通過反向跟蹤我們可以知道,這個錯誤發生在第5行,在bacon函數中;這次特定的bacon調用發生在第2行,spam函數中,而spam函數又是在第6行被調用的。這樣,在從多個位置調用函數的程式中,調用棧就能幫助你確定那次調用導致了錯誤。

調用 traceback.format_exc() 得到反向跟蹤的字元串形式

前面說過,如果拋出的異常沒有被處理,python才會顯示反向跟蹤。假如我們既想用except處理錯誤,又想要獲得出錯信息,就可以用這個函數,需要導入 traceback 模塊

例如,我們可以在程式出現錯誤時還能繼續運行,同時把錯誤信息記錄到日誌中。在程式結束後調試程式時,我們就根據日誌里記錄的信息去調試

>>> import traceback
>>> try:
    raise Exception('This is a error message')
except:
    errorFile=open('errorInfo.txt','w')
    errorFile.write(traceback.format_exc())  #使用tracback.format_exc()獲得反向跟蹤的字元串形式
    errorFile.close()
    print('The traceback info was written to errorInfo.txt')
 
     
112    #返回的是寫入的字元個數
The traceback info was written to errorInfo.txt
>>>

errorInfo.txt的內容:

Traceback (most recent call last):
  File "<pyshell#8>", line 2, in <module>
Exception: This is a error message

三、斷言assert語句

舉一個例子。你從學校畢業以後,很久都沒有找到工作,有一天你找了一個兼職:寶石大管家。小孩需要拿著與他們身份匹配的標識才能在別處領到寶石,這個標識在你這裡領取,你工作做得不錯,才做了五分鐘就被老闆任命為了區域經理,你覺你年紀輕輕就已經成為了二龍山雲霄飛車街區的揸Fit人、並且一手建立了二龍山游樂場寶石交易的游戲法則,覺得人生巔峰也不過如此,但是,沉迷於自我陶醉的你根本不知道,你將一個錯誤的標識給了一個小朋友,導致他沒有領到寶石。結果他叫他哥哥來打你了一頓。然後你老闆覺得你辜負了他對你的栽培,然後一氣之下把你開了,工資當然沒有結。最慘的是,你的衣服丟了,當時你為了用肚臍眼上的傷疤嚇唬他就把衣服脫了,結果他竟然也有同樣的傷疤,然後又被他打了一頓,然後,你的衣服就丟了。你知道這是你最寶貴的財富,因為這是當年女神贈你的禮物,你永遠也忘不了畢業那天,在你的寢室樓下,他輕輕的把袋子遞給了你,那天你們說了很多,他說感謝你四年來對他的照顧,但是他媽媽不讓他談戀愛,所以讓你再等等,你和他一直聊到晚上10點,只為了能當面向他說一句晚安,他很欣賞你的執著,離別之際對你許下了一個承諾:她說假如有一天這件衣服變成了綠色,他一定和你結婚。你知道,這下肯定沒有希望了。不僅失去了工作,你失去了愛情。你以為丟了衣服,就再也沒機會和他結婚了,萬萬沒想到,最後你們還是成為了夫妻。那天你回來以後就去了網吧,看見旁邊的人在寫代碼,他周圍散落的零食包裝代表著富有,這一切都被你看在眼裡,你知道你看到了希望,然後你就開始學編程了,由於你過人的天賦,沒出幾十年你就自己創辦了一家公司,和阿裡啪啪,中國移不動等大公司都建立了不同程度的合作關係,且業務往來十分密切,身邊的人都誇你有出息,只是在深夜的時候,你常常想起當年的那個他,你祈求老天再給你一次機會,終於有一天,你qq收到了他的信息,她說要來找你,你在城市最有檔次的地方約她吃飯,他一眼就認出來了你,你很開心,你覺得他一點都沒變,還是原來的樣子,他沒有問你衣服的事情,只是不停的向你道歉說是手誤當時才把你刪了,其實他這些年一直在找你,這次找到你了,就是要和你結婚,你十分激動,但是你強忍著激動的心情,勸他在考慮考慮,他搖了搖頭,從他眼神里流露出來的堅定瞬間擊垮了你,你再也控制不了自己了,你拿出了那次做兼職留下的寶石鑽戒,你一直把它帶在身上,就是等著機會到來,他想都沒想就一口答應了你的求婚。看到他對你如此信賴,你暗暗發誓一定要用全部的智商去愛她,晚上他非要枕著你的胳膊睡覺,你雖然覺的不舒服但還是讓他枕了一夜,你做了一個夢,夢見你們有了自己的孩子,那件衣服也被你找到了
衣服上還寫著“前方高能”幾個字,這是你睡得最舒服的一個晚上,你早早就醒來了,發現他也已經起來了,就在床邊上坐著,但令你不解的是,看到你睜開了眼睛,他的表情忽然很激動,sua的一聲就哭了,等他冷靜下來你才知道。原來,你應經昏迷了8年了,8年前,你去買早餐就再也沒有回來,你出了車禍,昏迷了8年,留下他和他腹中的孩子。他說這些年他從來沒有想過放棄你,他對你的愛幫助他剋服了許多困難。如今你醒了,他終於成功了,他高興的留下了激動的淚水,你也很開心。於是從此以後,你們一家三口過上了幸福的生活。

 

“斷言”在這個工作流程當中,就是用來檢查 你是否把牌發對了 的一個機制。為了避免這樣的情況,我們就添加“斷言”來檢查。

assert語句包含:

assert關鍵字、要判斷的條件、逗號、條件為False時顯示的字元串

>>> podBayDoorStatus='open'  #弔艙門的狀態
>>> assert podBayDoorStatus=='open','podBayDoorStatus需要設置為open'
#這裡結果沒有錯
>>> podBayDoorStatus='other content'
>>> assert podBayDoorStatus=='open','podBayDoorStatus需要設置為open'
#這裡結果出錯了
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    assert podBayDoorStatus=='open','podBayDoorStatus需要設置為open'
AssertionError: podBayDoorStatus需要設置為open
>>>

我們在程式中為某個變數賦值後,基於 這個變數是這個值 的假定,我們可能寫下了大量的代碼,即這些代碼依賴這個值,才能正確工作。說以我們添加一個斷言,確保假定的變數值是對的。

對於這種情況,我們使用assert讓程式立即崩潰就,以減少尋找缺陷的時間,我們不應用 try except 拋出異常,因為這是程式員的錯誤,而不是用戶的錯誤,對於那些可以恢復的錯誤(如文件沒有找到,用戶輸入了無效的數據)則應該用拋出異常來處理

  

在交通燈模擬中使用斷言

  

你在編寫一個交通信號燈的模擬程式。代表路口信號燈的數據結構是一個字典:

market_2nd={'ns':'green','ew':'red'}#ns南北向,ew東西向

你希望編寫一個函數 switchLight() ,他接受一個路口字典作為參數,並切換紅路燈

你可能認為 switchLight() 只要將每一種燈按順序切換到下一種顏色: ‘green‘ 值應該切換到 'yellow' , 'yellow' 應該切換到 'red' , 'red' 應該切換到 'green' 實現這個功能的代碼:

def switchLights(stoplight):
    for key in stoplight.keys():
        if stoplight[key]=='green':
            stoplight[key]='yellow'
        elif stoplight[key]=='yellow':
            stoplight[key]='red'
        elif stoplight[key]=='red':
            stoplight[key]='green'

這樣的運行結果:

>>>
 RESTART: C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\forTest.py
{'ns': 'yellow', 'ew': 'green'}
{'ns': 'red', 'ew': 'yellow'}
{'ns': 'green', 'ew': 'red'}

你應該發現第一次的輸出是錯誤的,因為南北向和東西向總應該有一個是紅色的,如果不是,那麼就會出現汽車相撞,為了避免這樣的缺陷出現,你應該添加斷言

market_2nd={'ns':'green','ew':'red'}#ns南北向,ew東西向
 
def switchLights(stoplight):
    for key in stoplight.keys():
        if stoplight[key]=='green':
            stoplight[key]='yellow'
        elif stoplight[key]=='yellow':
            stoplight[key]='red'
        elif stoplight[key]=='red':
            stoplight[key]='green'
    assert 'red' in stoplight.values(),'交通燈都不是紅色的'+str(stoplight)        #在函數裡面添加斷言
switchLights(market_2nd)
print(market_2nd)
switchLights(market_2nd)
print(market_2nd)
switchLights(market_2nd)
print(market_2nd)

假如你沒有看出來這個代碼有問題,然後也沒有使用斷言,當你從運行結果發現問題時,或許要好多時間才能發現問題出現在 stwitchLight 函數中

禁用斷言

當我們開發測試的時候,我們可以使用斷言來幫助我們更早的發現錯誤,但是程式交付的時候應該是沒有缺陷的,這時就不在需要斷言了,我們可以在運行python時傳入-O選項來禁用斷言

需要從終端視窗運行程式時使用 >>>從終端運行程式<<<

在這裡插入圖片描述

四、日誌

記日誌是一種很好的方式,讓我們可以理解程式中發生的事,以及事情發生的順序。python中的 logging 模塊讓你能很容易的創建自定義的消息記錄。這些日誌消息列出了你指定的 任何變數 當時的值。缺失日誌消息表明有一部分代碼被跳過了,從未執行

4.1使用日誌模塊

import logging
logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')

我們使用 logging.debug('string') 來列印日誌信息,這個 debug() 函數會調用 basicConfig ,所以我們第二行是指定列印信息的格式

python記錄一個時間的日誌時,他會創建一個 logRecord 對象,保存關於該事件的信息。

logging.debug() 調用不僅列印出了我們傳遞給他的信息,而且包含時間戳和一個單詞DEBUG

我們以下麵的程式為例,展示使用日誌來調試程式的大致過程

import logging
logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')
 
def factorial(n):
    logging.debug('Start of factorial(%s%%)' %(n))  #這裡的兩個%是什麼意思?或許是匹配basicConfig()里format里的後兩個參數?
    total=1
    for i in range(n+1):
        total*=i
        logging.debug('i is '+str(i)+', total is '+str(total))
    logging.debug('End of factorial(%s%%)'%(n))
    return total
 
print(factorial(5))
logging.debug('End of program')

運行結果:

RESTART: C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/facatorialLog.py
 2019-03-06 17:39:10,889 - DEBUG - Start of program
 2019-03-06 17:39:10,938 - DEBUG - Start of factorial(5%)
 2019-03-06 17:39:10,973 - DEBUG - i is 0, total is 0
 2019-03-06 17:39:11,001 - DEBUG - i is 1, total is 0
 2019-03-06 17:39:11,030 - DEBUG - i is 2, total is 0
 2019-03-06 17:39:11,058 - DEBUG - i is 3, total is 0
 2019-03-06 17:39:11,083 - DEBUG - i is 4, total is 0
 2019-03-06 17:39:11,108 - DEBUG - i is 5, total is 0
 2019-03-06 17:39:11,132 - DEBUG - End of factorial(5%)
0
 2019-03-06 17:39:11,187 - DEBUG - End of program

從裡面我們可以看到i是從0開始的,這就導致了total變數總是0,當然結果也是0,知道了這些,我們就可以對程式進行改動

import logging
logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')
 
def factorial(n):
    logging.debug('Start of factorial(%s%%)' %(n))
    #或許是匹配basicConfig()里format里的後兩個參數?
    total=1
    for i in range(1,n+1):    #改動在這裡
       
---snip--

PS:遇到問題沒人解答?需要Python學習資料?可以加點擊下方鏈接自行獲取
note.youdao.com/noteshare?id=2dce86d0c2588ae7c0a88bee34324d76

4.2日誌級別

這個級別是全局的

“日誌級別”提供了一種方式,按重要性把日誌消息分為了下麵5類。這些級別隻是一種建議,在工作中,還是有我們自己來為日誌消息指定類型。就像上面,我們也可以不用 logging.debug() 而選用其他四種

python中的日誌級別
|級別(上面的是最小的) |日誌函數 |描述|
|--|--|--|
DEBUG| logging.debug() |最低級別。用於小細節。通常你只有在診斷問題時才需要
INFO| logging.info() |用於記錄程式中一般事件的信息,或者是用來確認工作正常
WARNING| logging.warning() |用於表示可能的問題,這些問題不會阻止程式的工作,但將來可能會
ERROR| logging.error() |用於記錄錯誤,它導致程式做某事失敗
CRITICAL |logging.critical() |最高級別。用於表示致命的錯誤,它導致或將要導致程式完全停止工作
  
他們顯示的格式並區別

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
>>> logging.debug('Some debugging details')
 2019-03-06 18:13:44,829 - DEBUG - Some debugging details
>>> logging.info('The logging is working')
 2019-03-06 18:13:59,984 - INFO - The logging is working
>>> logging.critical('The program is unable to recover!')
 2019-03-06 18:14:34,237 - CRITICAL - The program is unable to recover!
>>>

“日誌級別”的好處

“日誌級別”的好處在於,你可以改變想看到的 日誌消息 的優先順序。這通過 basicConfig() 函數的level關鍵字參數來指定, level='logging.DEBUG' 時會顯示所有的日誌級別消息, level='logging.ERROR' 時只會顯示級別大於等於ERROR的日誌消息

當我們開發了更多程式後,我們可能只會對錯誤感興趣,這種情況,就可以通過上面的level參數來設定我們想看到的級別

4.3禁用日誌

logging.disable() 函數接受一個日誌級別,它會禁止該級別和更低級別的所有日誌消息,註意這個參數的書寫正確

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
>>> logging.critical('The program is unable to recover!')
 2019-03-06 18:14:34,237 - CRITICAL - The program is unable to recover!
>>> logging.disable(logging.CRITICAL)
>>> logging.critical('The program is unable to recover!')#由於上面的禁用這個就不顯示了
>>>

  
我們應該吧 logging.disable() 寫在程式中接近 import logging 代碼行的位置

4.4將日誌記錄到文件

logging.basicConfig() 函數接受 filename 關鍵字參數,日誌消息將被保存到 myProgramLog.txt 文件中,而不會在輸出在屏幕上

>>> import logging
>>>logging.basicConfig(filename='myProgramlog.txt',level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')

4.5 basicConfig 的參數及 logging 模塊定義的格式字元串欄位

參數名稱 描述
filename 指定日誌輸出目標文件的文件名,指定該設置項後日誌信心就不會被輸出到控制台了
filemode 指定日誌文件的打開模式,預設為'a'。需要註意的是,該選項要在filename指定時才有效
format 指定日誌格式字元串,即指定日誌輸出時所包含的欄位信息以及它們的順序。logging模塊定義的格式欄位下麵會列出。
datefmt 指定日期/時間格式。需要註意的是,該選項要在format中包含時間欄位%(asctime)s時才有效
level 指定日誌器的日誌級別
stream 指定日誌輸出目標stream,如sys.stdout、sys.stderr以及網路stream。需要說明的是,stream和filename不能同時提供,否則會引發 ValueError異常
style Python 3.2中新添加的配置項。指定format格式字元串的風格,可取值為'%'、'{'和'$',預設為'%'
handlers Python 3.3中新添加的配置項。該選項如果被指定,它應該是一個創建了多個Handler的可迭代對象,這些handler將會被添加到root logger。需要說明的是:filename、stream和handlers這三個配置項只能有一個存在,不能同時出現2個或3個,否則會引發ValueError異常。

五、IDLE的調試器  

"調試器"是IDLE的一項功能,他可以讓你每次執行一行代碼,並讓你清除的查看當前時刻所有變數的值,對於你弄明白程式的問題很有幫助,通過在交互視窗中點擊 Debug>Debugger 來打開 調試控制視窗

5.1視窗上的信息

調試的時候不要把把斷點打到類似while語句上,因為while這樣的語句只執行一次,執行多次的是裡面包裹的代碼,所以單步跳出或者繼續的時候就相當於繼續執行到這個while語句,結束了要想一次讓單步跳出或者繼續達到一次執行一輪 while裡面代碼的效果,就把斷點打到while裡面

打開調試視窗後,只要你運行程式調試器就會在第一條指令執行前暫停執行,並顯示下麵的信息:

將要執行的代碼行;所有局部變數其其值得列表;所有全局變數及其值的列表

你會發現這裡面有多你沒有定義的變數,如 __ builtins__ 、 __ doc__ 、 __ file__ ,等等。它們是python在運行程式時,自動設置的變數。這些變數代表的含義我現在也不知道。我們可以只關註那些我們定義的變數。

程式將保持暫停,知道我們按下調試視窗的5個按鈕中的一個:GO、Step、Over、Out、Quit

Go

點擊Go按鈕將導致程式正常執行至終止,或到達一個“斷點”(斷點稍後會說)。換句話說,如果你完成了調試,希望程式正常繼續,就點擊Go按鈕

Step

Step按鈕將導致程式執行下一行代碼,然後再次暫停。如果下一行代碼是一個函數調用,調試器就會“步入”那個函數,調到該函數的第一行。

Over

Over按鈕將執行下一行代碼,與Step按鈕類似。但是如果下一行代碼是一個函數調用,Over按鈕將“跨越”該函數的代碼,調試器將在該函數返回後暫停。例如,下一行代碼是 print() 調用,而顯然我們不關註 print() 這個函數的代碼是怎樣的工作的,只希望傳遞給它的字元串列印出來,這時我們就可以使用Over按鈕

Out

Out按鈕將導致調試器全速執行代碼行,直到它從當前函數返回。如果你用Step按鈕進入了一個函數,現在想要讓這個函數全速執行,直到這個函數結束,那麼就可以使用Out按鈕,讓他從當前函數調用中“走出來”

Quit

Quit按鈕將馬上終止該程式,不會執行下麵的代碼,記住是終止程式,不是終止調試

5.2關閉調試器

和打開的操作一樣,從互動式視窗點擊 Debug>Debugger 就會關閉

5.3斷點

“斷點”可以設置在特定的代碼行上,當使用調試器開始調試程式時,按下GO按鈕並不會結束程式了,而是會到達斷點里暫停。

我們可以在編輯器里在要設定斷點的行右擊滑鼠,選擇 Set Breakpoint ,就在當前行設置了斷點,並且會以亮黃色顯示,這次我們打開調試器後,再運行程式後按GO按鈕就會在這一行停止,當我們要清除斷點時,需要在當前行右擊滑鼠,選擇 clear Breakpoint

當我們想要知道for迴圈中某一輪中的變數值,我們就可以在那一行設置斷點,而不是頻繁的點擊Over按鈕

import random
mark=0
for i in range(1,1000):
    s=random.randint(0,2)
    if s==1:
        mark+=1
#我們查看迴圈到i=500時的mark值就可以在下麵設置斷點   
    if i==500:
       print('halfway done')    #設置這裡為斷點,而不要在上一行里設置,因為他是個判斷,每一輪都會運行
print(mark)

斷言、異常、日誌和調試器,都是在程式中發現錯誤和預防缺陷的有用工具。用python的斷言,是檢查自己有沒有犯錯的好方式。如果必要的條件被我們搞錯了,他將會早早的給出警告。斷言所針對的錯誤,是程式不應該嘗試恢復的,而是應該讓程式立馬失敗

異常可以由 try...except 語句捕捉和處理。 logging 模塊是一種很好的方式,可以在運行時查看代碼的內部,他比使用 pring() 語句要好很多,因為他有不同的日誌級別,並能寫入日誌文件。

調試器讓你每次單步執行一行代碼。或者可以用正常的速度運行程式,並讓調試器停在你設置的斷點的代碼行上。利用調試器,你可以看到程式在運行期間,任何時候所有變數的值。
轉自:https://www.cnblogs.com/Gaoqiking/p/10490368.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 什麼是狀態模式? 指的是對象內部狀態發生改變對象行為也會發生變化。 狀態模式主要解決的是當控制一個對象狀態的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把複雜的判斷邏輯簡化。 UML類圖 封裝變化 該模式中狀態是變化的,變化部分被做成了抽象類或介面,這讓做的目的就 ...
  • 基本思路 在每一次的排序中選出最小(或最大)的數,將其放在數組最前端,然後在後面的數中重覆此步驟,最終達到排序的目的. 演算法描述 將存於數組首位數與後面的數依次比較,將其中的較小的數放到數組放到數組首位 將除存於第二位的數視作首位,重覆第一步的操作 以此類推 代碼實現 這裡以從小到大排序為例 演算法分 ...
  • 冒泡排序(Bubble Sort) 一種電腦科學領域的較簡單的排序演算法。它重覆地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果順序(如從大到小、首字母從從Z到A)錯誤就把他們交換過來。走訪元素的工作是重覆地進行直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。 這個演算法的名字由來是因為越 ...
  • 進程,互斥鎖,生產者消費者,線程 一、僵屍進程與孤兒進程 代碼演示 二、子進程回收的兩種方式 代碼演示 三、進程守護 演示 四、進程間數據是隔離的 演示 五、進程互斥鎖 演示 六、隊列 演示 七、IPC(進程間通信) 演示 八、生產者與消費者 演示 子線程守護 十、線程互斥鎖 演示 ...
  • 編程只是 if ; 為了少寫重覆的代碼,有了迴圈 for/while; 但碰到很長的重覆代碼,可能用一個迴圈難以實現,所以出現了面向對象的思想: 類:就是你的迴圈主體 實例:就是對你的迴圈的一次調用 概念: 1. 在Python中,首字母大寫的,名稱指的是類。這個類定義中的括弧是空的 2. 類包括 ...
  • 本人第一次寫博客,之前都是用自己的日記本。 但是苦於不能時時帶著電腦,實在是不方便。。。。所以決定用手機。正好就是朋友也都在用博客,所以,,真香。。。 廢話不多說,點到為止。。 原理:比較兩個相鄰的元素,將值大的元素交換至右端。 冒泡排序的優點:每進行一趟排序,就會少比較一次,因為每進行一趟排序都會 ...
  • 大家好,歡迎來到樂位元組小樂的Java技術分享園地。這次給大家分享的是Tomcat 一. 什麼是 Tomcat Tomcat 是一個符合 JavaEE WEB 標準的最小的 WEB 容器,所有的 JSP 程式一定要有 WEB 容器的支持才能運行,而且在給定的 WEB 容器裡面都會支持事務處理操作。 T ...
  • 利用JavaFX設計一個井字棋游戲,其中包括了能夠與玩家對戰的AI。AI的實現相比五子棋來說要簡單得多,可以保證AI在後手情況下絕對不會輸,具體實現如下: /* * To change this license header, choose License Headers in Project Pr ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...