ArcGIS Python編程案例(12)-異常和錯誤處理

第十一章 使用加載項自定義ArcGIS界面 ||| 附錄A 自動執(zhí)行Python腳本


我們將在本章介紹以下案例:

  • 查看Python默認的錯誤消息
  • 添加Python異常處理語句結(jié)構(gòu)(try/except/finally)
  • 調(diào)用GetMessages()函數(shù)獲取工具消息
  • 使用嚴重性級別篩選工具消息
  • 調(diào)用GetMessage()返回單個消息
  • 測試并響應(yīng)特定錯誤消息

引言

ArcGIS地理處理工具和函數(shù)執(zhí)行過程中會返回不同的消息。這些消息包括信息性消息,也可能含有提示警告信息或錯誤狀況,這些警告或錯誤的出現(xiàn)意味著工具執(zhí)行完畢后沒有出現(xiàn)預(yù)期的結(jié)果或工具執(zhí)行完全失敗。不過這些消息并不是以消息框的形式顯示,你需要調(diào)用許多不同的ArcPy函數(shù)來訪問這些消息。到目前為止,我們都忽略了這些消息、提醒和錯誤。主要是因為希望你能專注于學(xué)習(xí)一些基本的概念,而沒有增加額外的代碼復(fù)雜度,而這些消息有關(guān)的代碼對于創(chuàng)建能夠處理錯誤狀況的地理處理腳本是非常有必要的。現(xiàn)在是時候來學(xué)習(xí)如何在Python中創(chuàng)建異常處理語句結(jié)構(gòu)。這些腳本可以處理在腳本執(zhí)行過程中生成的提示警告信息,錯誤信息和通用信息。這些異常處理語句會讓你的腳本更加靈活而且更不容易出現(xiàn)錯誤。你已經(jīng)使用了基本的tryexcept語句塊來執(zhí)行一些簡單的錯誤處理操作。在本章中,我們會介紹更多關(guān)于異常處理語句的細節(jié)內(nèi)容。

查看Python默認的錯誤消息

默認情況下,Python在腳本中一旦遇到問題就會生成錯誤消息。這些錯誤消息的內(nèi)容對于運行腳本的最終用戶來講并非總是那么明確具體。盡管如此,查看這些原始消息還是很有價值的。在后面的案例中,我們會使用Python錯誤處理語句結(jié)構(gòu)來了解錯誤信息以及能夠在必要時針對錯誤和異常情況作出反饋。

Getting ready

本案例中,我們會創(chuàng)建并運行一個有錯誤的腳本。在腳本中我們不會添加任何地理處理或Python異常處理結(jié)構(gòu)。這樣我們就能夠看到Python自身返回的錯誤消息。

How to do it...

按照以下步驟來查看Python自身生成的錯誤消息,該消息是由于工具在執(zhí)行過程中遇到錯誤生成的:
1.打開IDLE,創(chuàng)建一個新的腳本。
2.腳本保存為C:\ArcpyBook\Ch12\ErrorHandling.py文件。
3.導(dǎo)入arcpy模塊:

import arcpy

4.設(shè)置工作空間路徑:

arcpy.env.worksapce = "C:/ArcpyBook/data"

5.調(diào)用Buffer工具。Buffer工具需要一個緩沖距離作為其中一個參數(shù)。在代碼中我們故意舍掉距離參數(shù):

arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")

6.運行腳本。你會看到如下結(jié)果顯示:

Traceback (most recent call last): 
    File "<string>", line 3, in <module> 
        arcpy.Buffer_analysis("Streams.shp","Stream_buffer.shp")
    File "c:\program files\(x86)\arcgis\desktop10.1\arcpy\arcpy\analysis.py", line 687, in Buffer 
        raise e 
ExecuteError: Failed to execute. Parameters are not valid. 
ERROR 000735: Distance [value or field]: Value is required 
Failed to execute (Buffer).
How it works...

輸出的錯誤消息中的內(nèi)容似乎沒什么有用的信息。如果是一個有經(jīng)驗的程序員,通常能夠找到問題在于我們沒有提供緩沖距離參數(shù)。然而,很多情況下,返回的錯誤消息并不會給你解決問題提供很多幫助信息。代碼錯誤在編程中是不可避免的。如何理解這些稱為異常的錯誤是非常重要的。你可以使用Python異常處理語句結(jié)構(gòu)來有步驟地處理這些錯誤,而這些語句結(jié)構(gòu)會查看arcpy生成的異常信息并作出相對應(yīng)的反饋。如果缺少這些語句結(jié)構(gòu),腳本在執(zhí)行過程中很可能會隨時中斷或失敗,從而讓最終用戶懊惱。

添加Python異常處理結(jié)構(gòu)(try/except/finally)

Python內(nèi)置的異常處理語句結(jié)構(gòu)能夠捕獲腳本執(zhí)行中生成的錯誤消息。你可以利用這些錯誤信息為最終用戶提供一個更為明確的消息內(nèi)容并在必要時候作出反饋。

Getting ready

異常是代碼中的非正常或錯誤狀況。異常處理語句能夠捕獲并處理代碼中的錯誤,可以讓程序能夠從錯誤狀況中恢復(fù)。除了用來處理錯誤,異常處理語句還可用于其他方面,比如事件提醒和特殊情況處理等。
Python的異常有兩種發(fā)生方式。異常既可以捕獲也可以觸發(fā)。代碼中發(fā)生錯誤時,Python會自動觸發(fā)一個異常,這類異常有可能會在代碼中處理。作為一名程序員需要捕獲自動觸發(fā)的異常。異常還可以通過代碼方式進行人工觸發(fā)。這種情況下,你需要提供一個異常處理機制來捕獲這類人工觸發(fā)的異常。你可以使用raise語句來實現(xiàn)觸發(fā)異常。
try/except語句是Python中用來處理異常的一組完整的組合語句。try語句結(jié)構(gòu)是以try作為首行代碼,后面緊跟一組縮進的語句塊,之后是一個或多個可選的except語句用來命名捕獲的異常,最后是一個可選的else語句和finally語句。
下面以try/except/else語句結(jié)構(gòu)來說明運行機制。在try語句中,Python就會知道你現(xiàn)在正處于一個try語句塊中,一旦有異常發(fā)生就會直接交給后面的except語句進行處理。try語句塊中的每一行代碼都會執(zhí)行。假如沒有異常發(fā)生,代碼就會跳至else語句來執(zhí)行else語句中的代碼然后再執(zhí)行整個try/except/else語句塊后面的代碼。如果有異常發(fā)生,Python會查找相匹配的異常語句,如果找到了匹配的except語句,那么就會執(zhí)行該except語句中的代碼,之后執(zhí)行整個try/except/else語句塊后面的代碼。在這種情況下else語句則不會執(zhí)行。如果沒有找到匹配的except語句,那么在這種情況下,異常提交給最高層try語句中。這將導(dǎo)致一個無法處理的異常,也就會遇到我們在本章第一個案例中看到的錯誤消息。
本案例中,我們會添加一些基本的Python異常處理結(jié)構(gòu)語句。在本案例中,我們先介紹一個非常簡單的try/except語句結(jié)構(gòu)。

How to do it...

按照以下步驟在腳本中添加Python錯誤處理語句:
1.在IDLE中打開C:\ArcpyBook\Ch12\ErrorHandling.py文件。
2.在腳本中添加try/except語句:

import arcpy
try:
    arcpy.env.workspace = "C:/ArcpyBook/data"
    arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
    print "Error"

3.保存并修改腳本。你會看到一條簡答的消息顯示Error。這條信息沒有比我們在第一個案例中見到的結(jié)果更有幫助。事實上該消息的有用信息更少。本案例的目的只是介紹try/except語句結(jié)構(gòu)。

How it works...

這是一個非常簡單的結(jié)構(gòu)。try語句塊中的所有語句都會執(zhí)行。如果異常發(fā)生,語句會跳至except部分來打印錯誤消息,在本案例中也就是一個簡單的Error消息。如我之前所說,盡管這種消息對用戶難言有價值,但希望可以讓你對try/except語句的工作方式有個基本了解,同時作為一名程序員,你需要更好地了解程序反饋的任何錯誤。在下一個案例中,你會學(xué)習(xí)如何在異常處理結(jié)構(gòu)中獲取由地理處理工具生成的消息。

There's more...

另外一種try語句類型是try/finally語句,該語句可用于執(zhí)行終止操作。當(dāng)finally語句出現(xiàn)在try語句塊中使,無論是否發(fā)生異常或錯誤,finally語句部分在最后都會執(zhí)行。如果有異常發(fā)生,Python會執(zhí)行try語句塊,之后執(zhí)行finally語句塊,然后接著執(zhí)行整個try語句后面的代碼。如果執(zhí)行過程中沒有出現(xiàn)異常,Python會執(zhí)行try語句塊,之后執(zhí)行finally語句塊。不管錯誤是否發(fā)生都需要確保執(zhí)行某項操作時候,finally語句會非常有用。

調(diào)用GetMessages()獲取工具消息

ArcPy提供的GetMessages()函數(shù)用于獲取ArcGIS工具執(zhí)行過程中生成的消息。這些消息既包括像工具執(zhí)行的起始時間這樣的信息性消息,也包括由于未得到預(yù)期結(jié)果或工具執(zhí)行失敗生成的警告信息和錯誤信息。

Getting ready

工具執(zhí)行過程中會生成各種各樣的消息。這些消息包括消息性消息,比如工具執(zhí)行的開始和結(jié)束時間,工具使用的參數(shù)值以及進度消息。除此之外,工具還會生成警告消息和錯誤消息。這些消息可以通過Python腳本來讀取,同時還可以編寫代碼來處理出現(xiàn)的警告或錯誤消息。
ArcPy會保存上一次執(zhí)行的工具生成的消息,你可以調(diào)用GetMessages()函數(shù)來讀取這些消息,GetMessages()會返回一個包含了工具在上一次執(zhí)行中生成的所有消息的字符串。你可以使用嚴重性參數(shù)來篩選字符串以返回像警告消息或錯誤消息這樣特定類型的消息。第一條消息通常是工具的名稱,最后一條信息是工具執(zhí)行的開始和結(jié)束時間。
在本案例中,你會添加一行except語句,該語句用來打印關(guān)于當(dāng)前運行工具執(zhí)行過程中具體消息。

How to do it...

按照以下步驟來學(xué)習(xí)如何添加GetMessages()函數(shù)來生成工具執(zhí)行返回的消息列表。
1.在IDLE中打開C:\ArcpyBook\Ch12\ErrorHandling.py文件。
2.添加GetMessages()函數(shù):

import arcpy
try:
    arcpy.env.workspace = "C:/ArcpyBook/data"
    arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
    print arcpy.GetMessages()

3.保存并運行腳本。這一次返回的錯誤消息應(yīng)該會更為具體。你會注意到還有其他類型的消息返回,比如腳本執(zhí)行的開始和結(jié)束的時間等。

Executing: Buffer c:/ArcpyBook/data\Streams.shp c:/ArcpyBook/data\Streams_Buff.shp # FULL ROUND NONE #
Start Time: Tue Nov 13 22:23:04 2012
Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
Failed at Tue Nov 13 22:23:04 2012 (Elapsed Time: 0.00 seconds)
How it works...

GetMessages()函數(shù)返回上一次執(zhí)行工具過程中生成的所有的消息。這里需要要強調(diào)的是該函數(shù)僅返回上一次執(zhí)行的工具生成的消息。如果腳本中有多個工具執(zhí)行的話那就需要留意這一點。歷史記錄中執(zhí)行的工具過程生成的消息不能通過該函數(shù)獲取。不過,你可以使用Result對象獲取歷史記錄中工具運行的信息。

使用嚴重性級別篩選工具消息

如前面提到的那樣,所有的工具生成的消息可以分為消息性消息,警告消息和錯誤消息。GetMessages()函數(shù)可接受一個嚴重性級別參數(shù)用來篩選返回的消息。舉個例子,你可能只對工具執(zhí)行過程中生成的錯誤消息感興趣,對消息性消息和警告信息不感興趣。調(diào)用GetMessages(2)語句返回的消息中就僅包含錯誤消息。

Getting ready

任何消息都可以被歸類到三種消息類型中一類中,消息類型可以通過一個嚴重性級別來指定。信息性消息(Informational messages)提供與工具執(zhí)行有關(guān)的描述性信息,比如工具執(zhí)行進度,工具執(zhí)行的開始和結(jié)束時間,輸出數(shù)據(jù)特征等等。消息性消息的嚴重性級別用數(shù)字0來表示。警告消息(Warning messages)表示工具執(zhí)行過程中出現(xiàn)的問題可能影響輸出結(jié)果的時候生成。警告信息的嚴重性級別用數(shù)字1表示,同時并不會中止正在執(zhí)行的工具。最后一個類型是錯誤消息(error messages),該類型消息的嚴重性級別實用數(shù)字2表示。錯誤消息表示有嚴重事件阻止工具運行。工具執(zhí)行過程中會生成多個消息,這些消息都保存在列表中。更多關(guān)于消息嚴重性的信息見下圖。在本案例中,你將學(xué)習(xí)如何調(diào)用GetMessages()函數(shù)來篩選工具生成的消息。

How to do it...

篩選工具返回的消息非常簡單。你只要將想要返回的嚴重性級別相對應(yīng)的數(shù)字作為參數(shù)提供給GetMessages()函數(shù)即可。
1.在IDLE中打開C:\ArcpyBook\Ch12\ErrorHandling.py文件。
2.將數(shù)值2最為參數(shù)傳遞給GetMessages()函數(shù):

import arcpy
try:
    arcpy.env.workspace = "C:/ArcpyBook/data"
    arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
    print arcpy.GetMessages(2)

3.保存并運行腳本會看到如下結(jié)果:

Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
How it works...

如前所述,GetMessages()函數(shù)可接受0,1,2整數(shù)值參數(shù)。數(shù)值0表示返回消息性消息,而數(shù)值1表示返回警告消息。在本案例中,我們使用數(shù)值2表示我們只關(guān)注錯誤消息。這樣你在輸出結(jié)果中就不會看到腳本執(zhí)行的開始和結(jié)束時間這樣的信息性消息。

測試并響應(yīng)特定錯誤消息

所有的錯誤和警告都會生成一個特定的錯誤代碼。我們可以在腳本中來檢查特定的錯誤代碼,并基于這些錯誤代碼來執(zhí)行特定的操作。

Getting ready

地理處理工具的返回的錯誤和警告都包含一個六位數(shù)字代碼和一條描述性信息。你在腳本中可以檢測特定的錯誤代碼并作出相應(yīng)地反饋。你可以在ArcGIS幫助系統(tǒng)中的地理處理|工具錯誤和警告(Geoprocessing|Tool errors and warnings)中看到包含所有錯誤消息和代碼的列表。如下圖所示,所有的錯誤根據(jù)錯誤代碼都有一個對應(yīng)的描述頁面:

How to do it...

按照以下步驟來學(xué)習(xí)如何編寫代碼來響應(yīng)地理處理工具執(zhí)行過程中生成的特定的錯誤代碼:
1.點擊開始|所有程序|ArcGIS|ArcGIS Desktop 10幫助
(Start|Programs|ArcGIS|ArcGIS for Desktop Help)
打開幫助系統(tǒng)。
2.找到地理處理|工具錯誤和警告|工具錯誤1-10000|工具錯誤和警告:701-800(Geoprocessing|Tool errors and warnings|Tool errors 1-10000|Tool errors and warning:701-800)
3.選擇000735:<值>:需要值(000735:<value>:value is required)。該錯誤提示沒有提供工具需要的必選參數(shù)。我們在腳本中沒有提供緩沖距離參數(shù)導(dǎo)致了錯誤消息產(chǎn)生,其中包括了我們在幫助系統(tǒng)中看到的錯誤代碼(000735)。下面的消息代碼中,你會發(fā)現(xiàn)完整的錯誤消息文本。留意錯誤代碼(000735)。

ERROR000735:Distance[value or field]:Value is required

4.在IDLE中打開C:\ArcpyBook\Ch12\ErrorHandling.py文件。
5.如下所示修改腳本代碼:

except:
    print "Error found in Buffer tool \n"
    errCode = arcpy.GetReturnCode(3)
    if "735" in str(errCode):
        print "Distance value not provided \n"
        print "Running the buffer again with a default value \n"
        defaultDistance = "100 Feet"
        arcpy.Buffer_analysis("Steams.shp","Streams_Buff.shp",defaultDistance)
        print "Buffer complete"

6.保存并運行代碼。你會看到如下消息:

Error found in Buffer tool
Distance value not provided for buffer
Running the buffer again with a default distance value
Buffer complete
How it works...

我們在代碼中調(diào)用了arcpy.GetReturnCode()函數(shù)來返回工具生成的錯誤代碼。之后if語句用來檢測錯誤代碼中是否包含數(shù)值735,該代碼表示錯誤是由于沒有提供工具必選參數(shù)造成。接下來我們提供了一個緩沖距離值并再次調(diào)用Buffer工具。

調(diào)用GetMessage()函數(shù)返回單個消息

GetMessages()會返回上一次工具運行時生成的全部消息列表,不過你可以調(diào)用GetMessage()函數(shù)來獲取其中的單個消息。

Getting ready

到目前為止,我們都是返回工具生成的全部消息。不過,你可以調(diào)用GetMessage()函數(shù)為用戶返回單個消息,該函數(shù)接受一個整型參數(shù)來指定要返回的特定消息。工具生成的消息都是位于消息列表或數(shù)組中。
這里提醒一下,列表是零值開始計算索引值的,也就意味著了列表中的第一個元素的位置為0。比如,GetMessage(0)會返回列表中的第一條信息,而GetMessage(1)則返回第二條信息。第一條消息通常是當(dāng)前運行的工具名稱以及參數(shù)信息。第二條消息返回腳本運行的開始時間,而最后一條消息則返回腳本的結(jié)束時間。

How to do it...

1.在IDLE中打開C:\ArcpyBook\Ch12\ErrorHandling.py文件。
2.如下所示修改代碼:

import arcpy
try:
    arcpy.env.workspace = "C:/ArcpyBook/data"
    arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
except:
    print arcpy.GetMessage(1)
    print arcpy.GetMessage(arcpy.GetMessageCount()-1)

3.保存并運行腳本,你會看到如下結(jié)果顯示:

Start Time: Wed Nov 14 09:07:35 2012
Failed at Wed Nov 14 09:07:35 2012 (Elapsed Time: 0.00 seconds)
How it works...

我們之前沒有介紹GetMessageCount()函數(shù)。該函數(shù)返回工具生成的消息數(shù)量。記住消息列表是從零值開始索引,因此我們需要從GetMessageCount()返回的結(jié)果中減去1來獲取列表中的最后一條消息。否則的話,我們就是在試圖訪問列表中不存在的消息。在本案例中,我們獲取了腳本執(zhí)行的開始和結(jié)束時間。第二條消息通常是腳本執(zhí)行的開始時間,而最后一條消息則是腳本執(zhí)行的結(jié)束時間。下面的返回結(jié)果中則說明了這個問題:

Message 0 - Executing: Buffer c:/ArcpyBook/data\Streams.shp c:/ArcpyBook/ data\Streams_Buff.shp # FULL ROUND NONE # 
Message 1 - Start Time: Tue Nov 13 22:23:04 2012
Message 2 - Failed to execute. Parameters are not valid.
Message 3 - ERROR 000735: Distance [value or field]: Value is required
Message 4 - Failed to execute (Buffer).
Message 5 - Failed at Tue Nov 13 22:23:04 2012 (Elapsed Time: 0.00  seconds)

全部消息的數(shù)量為6,但是最后一條消息對應(yīng)的索引數(shù)為5。這也就是為什么我們要在腳本代碼中減去1的緣故。本案例中,由于腳本中發(fā)生錯誤,因此開始和結(jié)束時間相同。盡管如此,該案例仍然說明了如何來獲取由工具生成的單個消息。


第十一章 使用加載項自定義ArcGIS界面 ||| 附錄A 自動執(zhí)行Python腳本

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

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