python: 錯誤和異常

一、簡介

Python最強大的結(jié)構(gòu)之一就是它的異常處理能力,所有的標準異常都使用類來實現(xiàn),都是基類Exception的成員,都從基類Exception繼承,而且都在exceptions模塊中定義。Python自動將所有異常名稱放在內(nèi)建命名空間中,所以程序不必導(dǎo)入exceptions模塊即可使用異常。一旦引發(fā)而且沒有捕捉SystemExit異常,程序執(zhí)行就會終止。異常的處理過程、如何引發(fā)或拋出異常及如何構(gòu)建自己的異常類都是需要深入理解的。

二、詳解

1、什么是異常

(1)錯誤

從軟件方面來說,錯誤是語法或邏輯上的。語法錯誤指示軟件的結(jié)構(gòu)上有錯誤,導(dǎo)致不能被解釋器解釋或編譯器無法編譯。這些錯誤必須在程序執(zhí)行前糾正。邏輯錯誤可能是由于不完整或是不合法的輸入所致,在其他情況下,還可能是邏輯無法生成、計算或是輸出結(jié)果需要的過程無法執(zhí)行,這些錯誤通常分別被稱為域錯誤和范圍錯誤。
當(dāng)Python檢測到一個錯誤時,解釋器就會指出當(dāng)前流已經(jīng)無法繼續(xù)執(zhí)行下去。這時候就出現(xiàn)了異常。

(2)異常

對異常的最好描述是:它是因為程序出現(xiàn)了錯誤而在正常控制流以外采取的行為。這個行為又分為兩個階段:首先是引起異常發(fā)生的錯誤,然后是檢測和采取可能的措施階段。

第一個階段是在發(fā)生了一個異常條件(有時候也叫做例外的條件)后發(fā)生的。只要檢測到錯誤并且意識到異常條件,解釋器會引發(fā)一個異常。引發(fā)也可以叫做觸發(fā)、引發(fā)或者生成。 解釋器通過它通知當(dāng)前控制流有錯誤發(fā)生,Python也允許程序員自己引發(fā)異常。第二階段是:無論是 Python 解釋器還是程序員引發(fā)的,異常就是錯誤發(fā)生的信號, 當(dāng)前流將被打斷,用來處理這個錯誤并采取相應(yīng)的操作。對異常的處理發(fā)生在第二階段, 異常引發(fā)后,可以調(diào)用很多不同的操作。可以是忽略錯誤(記錄錯誤但不采取任何措施,采取補救措施后終止程序),或是減輕問題的影響后設(shè)法繼續(xù)執(zhí)行程序。所有的這些操作都代表一種繼續(xù),或是控制的分支。關(guān)鍵是程序員在錯誤發(fā)生時可以指示程序如何執(zhí)行。

Python采用了"try/嘗試"塊和"catching/捕獲"塊的概念,而且它在異常處理方面更有"紀律性"。可以為不同的異常創(chuàng)建不同的處理器, 而不是盲目地創(chuàng)建一個"catch-all/捕獲所有"的代碼。

2、Python中的異常

不管是通過Python解釋器執(zhí)行還是標準的腳本執(zhí)行,所有的錯誤都符合相似的格式, 這提供了一個一致的錯誤接口。所有錯誤,無論是語意上的還是邏輯上的,都是由于和Python解釋器不相容導(dǎo)致的,其后果就是引發(fā)異常。

NameError:嘗試訪問一個未申明的變量, 任何可訪問的變量必須在名稱空間里列出, 訪問變量需要由解釋器進行搜索,如果請求的名字沒有在任何名稱空間里找到,那么將會生成一個NameError異常。

ZeroDivisionError:除數(shù)為零;SyntaxError:Python 解釋器語法錯誤;IndexError:請求的索引超出序列范圍;KeyError:請求一個不存在的字典關(guān)鍵字;IOError:輸入/輸出錯誤;AttributeError:嘗試訪問未知的對象屬性。

3、檢測和處理異常

異常可以通過 try 語句來檢測,任何在try語句塊里的代碼都會被監(jiān)測, 檢查有無異常發(fā)生。try 語句有兩種主要形式: try-except和try-finally 。這兩個語句是互斥的, 即只能使用其中的一種。一個try語句可以對應(yīng)一個或多個except子句,但只能對應(yīng)一個finally子句,或是一個try-except-finally復(fù)合語句。可以使用try-except語句檢測和處理異常,也可以添加一個可選的else子句處理沒有探測到異常的時執(zhí)行的代碼,而try-finally只允許檢測異常并做一些必要的清除工作(無論發(fā)生錯誤與否)。

(1)try-except語句

try-except 語句(以及其更復(fù)雜的形式)定義了進行異常監(jiān)控的一段代碼,并且提供了處理異常的機制。
try-except 語句語法:

try:
    try_suite                  # watch for exceptions here監(jiān)控這里的異常
except Exception[, reason]:    # exception-handling code異常處理代碼
    except_suite

在程序運行時,解釋器嘗試執(zhí)行try塊里的所有代碼,如果代碼塊完成后沒有異常發(fā)生,執(zhí)行流就會忽略except語句繼續(xù)執(zhí)行。而當(dāng)except語句所指定的異常發(fā)生后,會保存了錯誤的原因,控制流立即跳轉(zhuǎn)到對應(yīng)的處理器(try子句的剩余語句將被忽略)。

(2)封裝內(nèi)建函數(shù)

交互操作:把一個用字符串表示的數(shù)值轉(zhuǎn)換為正確的數(shù)值表示形式,其中float()增加了把字符串表示的數(shù)值轉(zhuǎn)換為浮點數(shù)的功能,替換以前的string.atof()。 float()對參數(shù)要求嚴格,例如如果參數(shù)的類型正確(字符串),其值不可轉(zhuǎn)換為浮點數(shù),那么將引發(fā) ValueError異常;若參數(shù)是列表,因為類型不正確,所以引發(fā)一個TypeError異常。

def safe_float(obj):
    try:
        retval = float(obj)
    except ValueError:
        retval = 'could not convert non-number to float'
        return retval

(3)帶有多個except 的try語句

把多個except語句連接在一起, 處理一個try塊中可能發(fā)生的多種異常。

except Exception1[, reason1]:
    suite_for_exception_Exception1
except Exception2[, reason2]:
    suite_for_exception_Exception2

程序首先嘗試執(zhí)行try子句,如果沒有錯誤,忽略所有的except從句繼續(xù)執(zhí)行。如果發(fā)生異常,解釋器將在這一串處理器(except 子句)中查找匹配的異常, 如果找到對應(yīng)的處理器,執(zhí)行流將跳轉(zhuǎn)到這里。
Python支持把except語句串連使用,分別為每個異常類型分別創(chuàng)建對應(yīng)的錯誤信息,這樣用戶可以得到更詳細的關(guān)于錯誤的信息。

def safe_float(obj):
    try:
        retval = float(obj)
    except ValueError:
        retval = 'could not convert non-number to float'
    except TypeError:
        retval = 'object type cannot be converted to float'
        return retval

(4)處理多個異常的except語句

except 語句可以處理任意多個異常,但要求異常被放在一個元組里。
except (Exc1[, Exc2[, ... ExcN]])[, reason]:
suite_for_exceptions_Exc1_to_ExcN
如:

def safe_float(obj):
    try:
        retval = float(obj)
    except (ValueError, TypeError):
        retval = 'argument must be a number or numeric string'
        return retval

(5)捕獲所有異常

捕獲所有的異常的代碼:

try:
    pass
except Exception, e:
    # error occurred, log 'e', etc.

或不太推薦的方法是使用裸except子句(無任何錯誤信息,以后可能會不再支持):

try:
    pass
except:
    # error occurred, etc.

異常部分內(nèi)容在Python 2.5有了一些變化,異常被遷移到了new-style class上,啟用了一個新的"所有異常的母親",這個類叫做 BaseException。異常的繼承結(jié)構(gòu)有了少許調(diào)整,KeyboardInterrupt和SystemExit被從Exception里移出,和Exception平級。
- BaseException
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (all other current built-in exceptions) 所有當(dāng)前內(nèi)建異常

若需要捕獲所有異常,那么就可以使用新的BaseException:

try:
    pass
except BaseException, e:
    # handle all errors

注意:避免把大片的代碼裝入try-except中然后使用pass忽略掉錯誤,可以捕獲特定的異常并忽略它們,或是捕獲所有異常并采取特定的動作.,不要捕獲所有異常,然后忽略掉它們。

(6)異常參數(shù)

異常也可以有參數(shù),異常引發(fā)后它會被傳遞給異常處理器。當(dāng)異常被引發(fā)后參數(shù)是作為附加幫助信息傳遞給異常處理器的。雖然異常原因是可選的,但標準內(nèi)建異常提供至少一個參數(shù),指示異常原因的一個字符串。異常的參數(shù)可以在處理器里忽略, 但 Python提供了保存這個值的語法。要想訪問提供的異常原因,必須保留一個變量來保存這個參數(shù),把這個參數(shù)放在except語句后,接在要處理的異常后面。except 語句的這個語法可以被擴展為:

# single exception
except Exception[, reason]:
    suite_for_Exception_with_Argument
# multiple exceptions
except (Exception1, Exception2, ..., ExceptionN)[, reason]:
    suite_for_Exception1_to_ExceptionN_with_Argument

其中reason將會是一個包含來自導(dǎo)致異常的代碼的診斷信息的類實例。異常參數(shù)自身會組成一個元組,并存儲為類實例(異常類的實例)的屬性,reason將會是一個Exception類的實例。

無論reason只包含一個字符串或是由錯誤編號和字符串組成的元組,調(diào)用 str(reason) 總會返回一個良好可讀的錯誤原因,因為 reason是一個類實例,這樣其實是調(diào)用類的特殊方法str() 。

唯一的問題就是某些第三方或是其他外部庫并不遵循標準協(xié)議, 推薦在引發(fā)自己的異常時遵循異常參數(shù)規(guī)范,用和已有Python代碼一致錯誤信息作為傳給異常的參數(shù)元組的一部分。如:若引發(fā)一個ValueError,那么最好提供和解釋器引發(fā)ValueError時一致的參數(shù)信息。

(7)在應(yīng)用使用我們封裝的函數(shù)

處理一個文件,將其作為字符串讀入,并用一個日志文件跟蹤處理進程。

    #!/usr/bin/env python  
      
    def safe_float(object):  
        'safe version of float()'  
        try:  
            retval = float(object)  
        except (TypeError, ValueError), diag:  
            retval = str(diag)  
        return retval  
      
    def main():  
        'handles all the data processing'  
        log = open('cardlog.txt', 'w')  
        try:  
            ccfile = open('carddata.txt', 'r')  
        except IOError, e:  
            log.write('no txns this month\n')  
        log.close()  
            return  
      
        txns = ccfile.readlines()  
        ccfile.close()  
        total = 0.00  
        log.write('account log:\n')  
      
        for eachTxn in txns:  
            result = safe_float(eachTxn)  
            if isinstance(result, float):  
                total += result  
                log.write('data... processed\n')  
        else:  
            log.write('ignored: %s' % result)  
        print '$%.2f (new balance)' % (total)  
        log.close()  
      
    if __name__ == '__main__':  
        main()  

其中從文件中提取數(shù)據(jù),這里的文件打開被置于try-except語句段中。內(nèi)建的isinstance()函數(shù)檢查結(jié)果類型,檢查safe_float是返回字符串還是浮點數(shù),任何字符串都意味著錯誤,表明該行不能轉(zhuǎn)換為數(shù)字,同時所有的其他數(shù)字可以作為浮點數(shù)累加入total,在 main()函數(shù)的尾行會顯示最終生成的余額。

(8)else子句

在try范圍中沒有異常被檢測到時即結(jié)束前沒有引發(fā)異常,然后執(zhí)行else子句。如:

try:
    function()
except:
    pass
else:
    pass

(9)finally子句

finally子句是無論異常是否發(fā)生、是否捕捉都會執(zhí)行的一段代碼。可以將finally僅僅配合try一起使用,也可以和 try-except(else也是可選的)一起使用。
try-except-else-finally 語法的示例:

try:
    A
except MyException:
    B
else:
    C
finally:
    D

(10)try-finally語句

另一種使用finally的方式是finally單獨和try連用。這個try-finally語句和try-except區(qū)別在于它不是用來捕捉異常的。作為替代,它常常用來維持一致的行為,無論 try中是否有異常觸發(fā),finally 代碼段都會被執(zhí)行。

try:
    try_suite
finally:          #無論如何都執(zhí)行
    finally_suite

當(dāng)在try范圍中產(chǎn)生一個異常時,會立即跳轉(zhuǎn)到finally語句段。當(dāng)finally中的所有代碼都執(zhí)行完畢后,會繼續(xù)向上一層引發(fā)異常。
讀取數(shù)據(jù)的代碼:

try:  
    ccfile = open('carddata.txt', 'r')  
    txns = ccfile.readlines()  
    ccfile.close()  
except IOError:  
    log.write('no txns this month\n') 

其中的缺陷:若按照這樣的順序發(fā)生錯誤,打開成功但出于一些原因readlines()調(diào)用失敗,異常處理會去繼續(xù)執(zhí)行except中的子句,而不去嘗試關(guān)閉文件。通過try-finally來優(yōu)化:

ccfile = None  
try:  
    try:  
        ccfile = open('carddata.txt', 'r')  
        txns = ccfile.readlines()  
    except IOError:  
        log.write('no txns this month\n')  
finally:  
    if ccfile:  
        ccfile.close() 

另一種可選的實現(xiàn)切換了try-except和try-finally包含的方式:

ccfile = None  
try:  
    try:  
        ccfile = open('carddata.txt', 'r')  
        txns = ccfile.readlines()  
    finally:  
        if ccfile:  
            ccfile.close()  
except IOError:  
    log.write('no txns this month\n') 

上述方法唯一的問題是:當(dāng)finally中的代碼引發(fā)了另一個異常或由于return、break、continue語法而終止,會丟失原來異常的上下文信息導(dǎo)致原來的異常無法重新引發(fā),除非也事先保存。

(11)try-except-else-finally:廚房一鍋端

語法樣式:

try:
    try_suite
except Exception1:
    suite_for_Exception1
except (Exception2, Exception3, Exception4):
    suite_for_Exceptions_2_3_and_4
except Exception5, Argument5:
    suite_for_Exception5_plus_argument
except (Exception6, Exception7), Argument67:
    suite_for_Exceptions6_and_7_plus_argument
except:
    suite_for_all_other_exceptions
else:
    no_exceptions_detected_suite
finally:
    always_execute_suite

其中else和finally都是可選的,而必須至少要有一個except子句。

4、上下文管理

(1)with 語句

另一個隱藏低層次的抽象的例子是with語句,它在Python 2.6中正式啟用(以前必必須用from future import with_statement來導(dǎo)入它)。
with 語句的目的在于從流程圖中把try、except和finally關(guān)鍵字和資源分配釋放相關(guān)代碼統(tǒng)統(tǒng)去掉,而不是像try-except-finally那樣僅僅簡化代碼使之易用。 with 語法的基本用法:

with context_expr [as var]:
    with_suite

file和with一起使用的代碼片段:

with open('/etc/passwd', 'r') as f:
    for eachLine in f:
         # ...do stuff with eachLine or f...

這段代碼試圖打開一個文件,如果一切正常,把文件對象賦值給f;然后用迭代器遍歷文件中的每一行,當(dāng)完成時關(guān)閉文件。無論在這一段代碼的開始、中間還是結(jié)束時發(fā)生異常,都會執(zhí)行清理的代碼,此外文件仍會被自動的關(guān)閉。可以看出Python已經(jīng)拿走了一堆細節(jié),實際上只是進行了兩層處理:第一,用戶層 ,和in類似所需要關(guān)心的只是被使用的對象;第二,對象層,既然這個對象支持上下文管理協(xié)議,它干的也就是"上下文管理"。

5、字符串作為異常

早在Python 1.5前,標準的異常是基于字符串實現(xiàn)的。然而,這樣就限制了異常之間不能有相互的關(guān)系,這種情況隨著異常類的來臨而不復(fù)存在。到1.5后,所有的標準異常都是類了,但程序員還是可以用字符串作為自己的異常的(建議使用異常類)。在2.5中,觸發(fā)字符串異常會導(dǎo)致一個警告,2.6中捕獲字符串異常會導(dǎo)致一個警告。

6、觸發(fā)異常

有些異常由程序執(zhí)行期間的錯誤而引發(fā),程序員在編寫API時希望遇到錯誤的輸入時觸發(fā)異常,為此Python提供了一種機制讓程序員明確的觸發(fā)異常,即raise語句。

(1)raise語法

raise 語句支持的參數(shù)十分靈活,語法上支持許多不同的格式。rasie一般的用法:raise [SomeException [, args [, traceback]]]。
第一個參數(shù),SomeExcpetion是觸發(fā)異常的名字。如果有,它必須是一個字符串、類或?qū)嵗H绻衅渌麉?shù)(arg或traceback),就必須提供SomeExcpetion.Python的標準異常。
第二個符號為可選的args(比如參數(shù),值)來傳給異常,這可以是一個單獨的對象也可以是一個對象的元組。當(dāng)異常發(fā)生時,異常的參數(shù)總是作為一個元組傳入。如果args原本就是元組,那么就將其傳給異常去處理;如果args是一個單獨的對象,就生成只有一個元素的元組(就是單元素元組)。大多數(shù)情況下,單一的字符串用來指示錯誤的原因。如果傳的是元組,通常的組成是一個錯誤字符串,一個錯誤編號,可能還有一個錯誤的地址比如文件等等。
最后一項參數(shù)traceback,同樣是可選的(實際上很少用它)。如果有的話,則是當(dāng)異常觸發(fā)時新生成的一個用于異常-正常化(exception-normally)的追蹤(traceback)對象。當(dāng)你想重新引發(fā)異常時,第三個參數(shù)很有用(可以用來區(qū)分先前和當(dāng)前的位置)。如果沒有這個參數(shù),就填寫None。

(2) raise慣用法

最常見的用法為SomeException是一個類,不需要其他的參數(shù),但如果有的話,可以是一個單一對象參數(shù)、一個參數(shù)的元組或一個異常類的實例。如果參數(shù)是一個實例,可以由給出的類及其派生類實例化(已存在異常類的子集)。若參數(shù)為實例,則不能有更多的其他參數(shù)。

(3)raise少見的慣用法

當(dāng)參數(shù)是一個實例 , 該實例若是給定異常類的實例當(dāng)然不會有問題,然而如果該實例并非這個異常類或其子類的實例時,那么解釋器將使用該實例的異常參數(shù)創(chuàng)建一個給定異常類的新實例。 如果該實例是給定異常類子類的實例, 那么新實例將作為異常類的子類出現(xiàn), 而不是原來的給定異常類。
如果raise語句的額外參數(shù)不是一個實例——作為替代,是一個單件(singleton)或元組,那么將用這些作為此異常類的初始化的參數(shù)列表。如果不存在第二個參數(shù)或是None,則參數(shù)列表為空。
如果SomeException是一個實例,就無需對什么進行實例化了。這種情況下,不能有額外的參數(shù)或只能是None。異常的類型就是實例的類;也就是說,等價于觸發(fā)此類異常,并用該實例為參數(shù)比如:raiseinstance.class,instance。
還有一個可選的參量(args)作參數(shù).
最后,這種不含任何參數(shù)的raise語句結(jié)構(gòu)是在Python1.5中新引進的,會引發(fā)當(dāng)前代碼塊(code block)最近觸發(fā)的一個異常。如果之前沒有異常觸發(fā),會因為沒有可觸發(fā)的異常而生成一TypeError異常。

(4)raise的不同用法

由于raise有許多不同格式有效語法(比如:SomeException 可以是類、實例或一個字符串),以下總結(jié)下rasie 的不同用法:


7、斷言

斷言是一句必須等價于布爾真的判定;此外,發(fā)生異常也意味著表達式為假(類似C中預(yù)處理器的assert宏),但在Python中它們在運行時構(gòu)建(與之相對的是編譯期判別)。 斷言通過 assert 語句實現(xiàn)。可以簡簡單單的想象為raise-if語句(更準確的說是raise-if-not 語句)。測試一個表達式,若返回值是假,觸發(fā)異常。
斷言語句,如果斷言成功不采取任何措施(類似語句),否則觸發(fā)AssertionError(斷言錯誤)的異常。assert 的語法如下:assert expression[, arguments]。AssertionError異常和其他的異常一樣可以用try-except語句塊捕捉,但是如果沒有捕捉,它將終止程序運行而且提供一個traceback。
如同raise 語句一樣,也可以提供一個異常參數(shù)給assert 命令:

    >>> try:  
    ...     assert 1 == 0, 'One does not equal zero silly!'  
    ... except AssertionError, args:  
    ...     print '%s: %s' % (args.__class__.__name__, args)  
    ...   
    AssertionError: One does not equal zero silly!  

assert 如何運作,可以通過函數(shù)類似實現(xiàn)(內(nèi)建的變量debug在通常情況下為True):

def assert(expr, args=None):
    if __debug__ and not expr:
        raise AssertionError, args

8、標準異常

所有的異常都是內(nèi)建的, 所以它們在腳本啟動前或在互交命令行提示符出現(xiàn)時已經(jīng)是可用的了。
Python內(nèi)建異常:





所有的標準/內(nèi)建異常都是從根異常派生的。目前有3個直接從BaseException派生的異常子類:SystemExit、KeyboardInterrupt和Exception,其他的所有的內(nèi)建異常都是Exception的子類。
到了Python2.5,所有的異常的都是新風(fēng)格(new-style)的類,并且最終都是BaseException的子類。從Python1.5到Python2.4.x,異常是標準的類,它們是字符串。從Python2.5開始,不再支持構(gòu)建基于字符串的異常并且被正式的棄用,即不能再觸發(fā)一個字符串異常了,將不能捕獲它們。還有一個就是所有新的異常最終都是BaseException的子類,以便于它們有一個統(tǒng)一的接口。

9、sys和相關(guān)模塊

(1)sys模塊

另一種獲取異常信息的途徑是通過sys模塊中exc_info()函數(shù),此功能提供了一個3元組(3-tuple)的信息。

    >>> try:  
    ...     float('abc123')  
    ... except:  
    ...     import sys  
    ...     exc_tuple = sys.exc_info()  
    ...   
    >>> print exc_tuple  
    (<type 'exceptions.ValueError'>, ValueError('invalid literal for float(): abc123',), <traceback object at 0x7ff79c87dc20>)  
    >>> for eachItem in exc_tuple:  
    ...     print eachItem  
    ...   
    <type 'exceptions.ValueError'>  
    invalid literal for float(): abc123  
    <traceback object at 0x7ff79c87dc20>  

sys.exc_info()得到的元組中是:exc_type異常類;exc_value異常類的實例;exc_traceback追蹤(traceback)對象。第三項,,是一個新增的追蹤(traceback)對象,這一對象提供了的發(fā)生異常的上下文,它包含諸如代碼的執(zhí)行幀,異常發(fā)生時的行號等信息。在舊版本中的Python中,這三個值分別存在于sys模塊,為sys.exc_type、sys.exc_value和sys.exc_traceback ,但這三者是全局變量而不是線程安全的, 建議用sys.exc_info()來代替。

(2)相關(guān)模塊

模塊 描述
exceptions 內(nèi)建異常(永遠不用導(dǎo)入這個模塊)
contextlib 為使用 with 語句的上下文對象工具
sys 包含各種異常相關(guān)的對象和函數(shù)(見sys.ex)

三、總結(jié)

(1)Python異常不僅簡化代碼,而且簡化整個錯誤管理體系,異常處理促使成熟和正確的編程。
(2)可以通過創(chuàng)建一個從內(nèi)置的Exception類繼承的類定義自己的異常,然后使用raise命令引發(fā)異常或傳遞異常。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內(nèi)容