最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python?schedule庫(kù)實(shí)現(xiàn)定時(shí)任務(wù)的避坑指南

 更新時(shí)間:2026年03月18日 08:27:47   作者:竹林818  
想把 schedule 用在一個(gè)需要長(zhǎng)期穩(wěn)定運(yùn)行的生產(chǎn)環(huán)境里,遠(yuǎn)不是幾行示例代碼那么簡(jiǎn)單,這篇文章主要介紹了Python?schedule庫(kù)實(shí)現(xiàn)定時(shí)任務(wù)的踩坑和填坑全過(guò)程,感興趣的小伙伴可以了解下

背景:一個(gè)不能停的同步服務(wù)

上個(gè)月,團(tuán)隊(duì)里一個(gè)老舊的內(nèi)部數(shù)據(jù)同步腳本掛了,導(dǎo)致下游好幾個(gè)報(bào)表數(shù)據(jù)延遲。領(lǐng)導(dǎo)把重構(gòu)的任務(wù)交給了我,核心要求就一個(gè):要穩(wěn)定,要能7x24小時(shí)跑,不能動(dòng)不動(dòng)就悄無(wú)聲息地停了。

這個(gè)腳本原本就是寫(xiě)在一個(gè)死循環(huán)里,用 time.sleep(300) 來(lái)每隔5分鐘同步一次數(shù)據(jù)。問(wèn)題很明顯:腳本本身沒(méi)有監(jiān)控,掛了沒(méi)人知道;sleep 的時(shí)候整個(gè)進(jìn)程啥也干不了;日志全混在一起,出問(wèn)題了很難查。

我的第一反應(yīng)就是找個(gè)成熟的定時(shí)任務(wù)庫(kù)。APScheduler 功能強(qiáng)大但略顯臃腫,Celery 又得搭消息隊(duì)列。對(duì)于這個(gè)簡(jiǎn)單的、單進(jìn)程的同步需求,我相中了輕量級(jí)的 schedule 庫(kù)。它API簡(jiǎn)單直觀,schedule.every(5).minutes.do(job) 這種寫(xiě)法,一看就懂。

但很快我就發(fā)現(xiàn),想把 schedule 用在一個(gè)需要長(zhǎng)期穩(wěn)定運(yùn)行的生產(chǎn)環(huán)境里,遠(yuǎn)不是幾行示例代碼那么簡(jiǎn)單。下面就是我一路踩坑、填坑的全過(guò)程。

問(wèn)題分析:為什么簡(jiǎn)單的循環(huán)不靠譜?

一開(kāi)始,我照著官方示例,寫(xiě)了一個(gè)最基礎(chǔ)的版本:

import schedule
import time

def sync_data():
    print("開(kāi)始同步數(shù)據(jù)...")
    # 模擬一些工作
    time.sleep(10)
    print("數(shù)據(jù)同步完成!")

# 每5分鐘執(zhí)行一次
schedule.every(5).minutes.do(sync_data)

while True:
    schedule.run_pending()
    time.sleep(1)

跑起來(lái)一看,好像沒(méi)問(wèn)題。但我馬上意識(shí)到兩個(gè)致命傷:

  • 任務(wù)阻塞問(wèn)題:我的 sync_data 函數(shù)模擬了10秒的工作。如果實(shí)際工作耗時(shí)超過(guò)了5分鐘的間隔會(huì)怎樣?schedule 會(huì)等當(dāng)前任務(wù)完成,再立刻執(zhí)行下一次,導(dǎo)致任務(wù)堆積。更糟的是,在任務(wù)執(zhí)行的這10秒里,while 循環(huán)卡在 sync_data 里,run_pending() 根本不會(huì)被調(diào)用,整個(gè)定時(shí)機(jī)制在任務(wù)運(yùn)行時(shí)是“失靈”的。
  • 異常處理缺失:如果 sync_data 里拋出一個(gè)異常,整個(gè)腳本就會(huì)崩潰退出。這對(duì)于一個(gè)需要無(wú)人值守的服務(wù)來(lái)說(shuō)是災(zāi)難性的。

我需要的是一個(gè)非阻塞的、健壯的定時(shí)任務(wù)執(zhí)行器。這意味著任務(wù)必須在獨(dú)立的線程中運(yùn)行,并且任何異常都不能導(dǎo)致主程序退出。

核心實(shí)現(xiàn):構(gòu)建健壯的定時(shí)任務(wù)骨架

第一步:把任務(wù)丟進(jìn)線程里跑

解決阻塞問(wèn)題的核心思路是:讓 schedule.run_pending() 這個(gè)調(diào)度循環(huán)永遠(yuǎn)保持流暢運(yùn)行,不被具體任務(wù)阻塞。所以,每個(gè)任務(wù)都應(yīng)該在一個(gè)獨(dú)立的線程中執(zhí)行。

我創(chuàng)建了一個(gè)包裝函數(shù) run_threaded

import threading
import schedule
import time
import logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def run_threaded(job_func):
    """將任務(wù)函數(shù)放入線程中執(zhí)行"""
    job_thread = threading.Thread(target=job_func)
    job_thread.start()
    # 注意:這里我們不調(diào)用 job_thread.join()

這里有個(gè)關(guān)鍵細(xì)節(jié):我們只 start() 線程,不 join()。join() 會(huì)阻塞當(dāng)前線程(也就是調(diào)度線程),等待工作線程結(jié)束,這又回到了老路上。我們讓工作線程自己“放飛”,調(diào)度線程繼續(xù)它的循環(huán)。

然后這樣使用:

schedule.every(5).minutes.do(run_threaded, sync_data)

第二步:給任務(wù)加上“安全氣囊”

任務(wù)在線程里跑,線程里的異常默認(rèn)是不會(huì)傳遞到主線程的。這避免了腳本崩潰,但壞處是:任務(wù)悄無(wú)聲息地失敗了,我們可能毫無(wú)察覺(jué)。

所以,必須在任務(wù)函數(shù)內(nèi)部做好異常捕獲,并進(jìn)行妥善的日志記錄。我改造了任務(wù)函數(shù):

def sync_data():
    """數(shù)據(jù)同步任務(wù)"""
    try:
        logger.info("數(shù)據(jù)同步任務(wù)開(kāi)始。")
        # 這里是你的核心業(yè)務(wù)邏輯,比如調(diào)用API、讀寫(xiě)數(shù)據(jù)庫(kù)等
        time.sleep(10)  # 模擬耗時(shí)操作
        # 模擬一個(gè)可能的錯(cuò)誤
        # 1 / 0
        logger.info("數(shù)據(jù)同步任務(wù)成功完成。")
    except Exception as e:
        # 捕獲所有異常,記錄錯(cuò)誤日志,避免線程異常導(dǎo)致整個(gè)程序退出
        logger.error(f"數(shù)據(jù)同步任務(wù)發(fā)生嚴(yán)重錯(cuò)誤: {e}", exc_info=True)

注意這個(gè)細(xì)節(jié)logger.error 中使用了 exc_info=True,這會(huì)讓日志記錄完整的異常堆棧信息,對(duì)于后期調(diào)試至關(guān)重要。現(xiàn)在,無(wú)論任務(wù)里發(fā)生什么,錯(cuò)誤都會(huì)被記錄在案,而調(diào)度器會(huì)繼續(xù)淡定地運(yùn)行下一個(gè)周期。

第三步:讓調(diào)度循環(huán)本身也堅(jiān)不可摧

即使每個(gè)任務(wù)都包好了,調(diào)度主循環(huán) while True 里如果出問(wèn)題(雖然概率極低),腳本還是會(huì)掛。所以,最外層的循環(huán)也要加保護(hù):

def run_scheduler():
    """運(yùn)行調(diào)度器的循環(huán)"""
    logger.info("定時(shí)任務(wù)調(diào)度器開(kāi)始運(yùn)行...")
    while True:
        try:
            schedule.run_pending()
            time.sleep(1)  # 避免CPU空轉(zhuǎn)
        except KeyboardInterrupt:
            logger.info("接收到中斷信號(hào),調(diào)度器正在停止...")
            break
        except Exception as e:
            # 捕獲調(diào)度器本身的未知異常,記錄并繼續(xù)運(yùn)行
            logger.critical(f"調(diào)度器主循環(huán)發(fā)生未知異常: {e}", exc_info=True)
            time.sleep(60)  # 發(fā)生嚴(yán)重錯(cuò)誤時(shí),等待一分鐘再重試循環(huán)

這里做了兩件事:

  • 優(yōu)雅地處理 KeyboardInterrupt(比如在控制臺(tái)按Ctrl+C),讓程序可以正常退出。
  • 用一個(gè)更寬的 except 兜底,萬(wàn)一 run_pending() 本身有bug,我們記錄一個(gè)最高級(jí)別(CRITICAL)的日志,然后等待一段時(shí)間后繼續(xù)嘗試,而不是直接退出。

第四步:管理多個(gè)任務(wù)與資源競(jìng)爭(zhēng)

服務(wù)不止一個(gè)同步任務(wù),還有清理臨時(shí)文件、發(fā)送心跳檢測(cè)等。當(dāng)多個(gè)任務(wù)可能操作同一資源(比如同一個(gè)文件、同一個(gè)數(shù)據(jù)庫(kù)表)時(shí),就需要引入鎖(threading.Lock)來(lái)避免競(jìng)爭(zhēng)。

# 創(chuàng)建一個(gè)全局鎖,用于保護(hù)共享資源
data_file_lock = threading.Lock()

def sync_data():
    try:
        logger.info("數(shù)據(jù)同步任務(wù)開(kāi)始。")
        # 在操作共享文件前獲取鎖
        with data_file_lock:
            logger.info("獲取到文件鎖,開(kāi)始寫(xiě)入數(shù)據(jù)...")
            time.sleep(5)  # 模擬文件操作
            logger.info("數(shù)據(jù)寫(xiě)入完成,釋放文件鎖。")
        logger.info("數(shù)據(jù)同步任務(wù)成功完成。")
    except Exception as e:
        logger.error(f"數(shù)據(jù)同步任務(wù)發(fā)生錯(cuò)誤: {e}", exc_info=True)

這里有個(gè)坑:鎖的使用要非常小心,只在必要的最小代碼塊上加鎖,并且確保鎖一定能被釋放(使用 with 語(yǔ)句是很好的習(xí)慣),否則會(huì)導(dǎo)致死鎖,其他任務(wù)會(huì)永遠(yuǎn)等待下去。

完整代碼

下面是我最終用于生產(chǎn)環(huán)境的完整示例代碼,你可以直接復(fù)制,根據(jù)你的任務(wù)修改 sync_data、cleanup_temp 等函數(shù)的內(nèi)容。

"""
一個(gè)健壯的、基于 schedule 庫(kù)的 Python 定時(shí)任務(wù)執(zhí)行器。
適用于需要 7x24 小時(shí)運(yùn)行的后臺(tái)服務(wù)。
"""
import schedule
import time
import threading
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)

# 示例:用于保護(hù)共享資源的鎖
shared_resource_lock = threading.Lock()

def run_threaded(job_func):
    """
    將任務(wù)函數(shù)放入獨(dú)立線程中執(zhí)行,避免阻塞主調(diào)度循環(huán)。
    Args:
        job_func: 要執(zhí)行的任務(wù)函數(shù)
    """
    job_thread = threading.Thread(target=job_func, name=job_func.__name__)
    job_thread.start()
    # 重要:不在此處join,防止阻塞調(diào)度器。

def sync_data():
    """示例任務(wù)1:模擬數(shù)據(jù)同步"""
    task_name = "數(shù)據(jù)同步"
    try:
        logger.info(f"[{task_name}] 任務(wù)開(kāi)始。")
        # 模擬一些網(wǎng)絡(luò)I/O或數(shù)據(jù)庫(kù)操作
        time.sleep(12)  # 假設(shè)本次執(zhí)行需要12秒
        # 模擬操作共享資源
        with shared_resource_lock:
            logger.info(f"[{task_name}] 獲取鎖,操作共享資源...")
            time.sleep(1)
        # 模擬一個(gè)偶然的錯(cuò)誤(取消注釋來(lái)測(cè)試)
        # if datetime.now().second % 10 == 0:
        #     raise ConnectionError("模擬網(wǎng)絡(luò)突然斷開(kāi)")
        logger.info(f"[{task_name}] 任務(wù)成功完成。")
    except Exception as e:
        logger.error(f"[{task_name}] 執(zhí)行失敗: {e}", exc_info=True)

def cleanup_temp():
    """示例任務(wù)2:模擬清理臨時(shí)文件"""
    task_name = "清理臨時(shí)文件"
    try:
        logger.info(f"[{task_name}] 任務(wù)開(kāi)始。")
        time.sleep(3)  # 模擬清理工作
        logger.info(f"[{task_name}] 任務(wù)完成。")
    except Exception as e:
        logger.error(f"[{task_name}] 執(zhí)行失敗: {e}", exc_info=True)

def send_heartbeat():
    """示例任務(wù)3:發(fā)送心跳信號(hào),證明調(diào)度器還活著"""
    try:
        # 這是一個(gè)非??斓娜蝿?wù),不需要放線程也行,這里為了統(tǒng)一也放了。
        logger.info("心跳檢測(cè):調(diào)度器運(yùn)行正常。")
    except Exception as e:
        logger.error(f"心跳任務(wù)失敗: {e}", exc_info=True)

def run_scheduler():
    """調(diào)度器主循環(huán)"""
    logger.info("=== 定時(shí)任務(wù)調(diào)度器啟動(dòng) ===")

    # 1. 定義任務(wù)調(diào)度規(guī)則
    # 每5分鐘執(zhí)行一次數(shù)據(jù)同步(使用線程)
    schedule.every(5).minutes.do(run_threaded, sync_data)
    # 每小時(shí)執(zhí)行一次清理
    schedule.every().hour.do(run_threaded, cleanup_temp)
    # 每30秒發(fā)送一次心跳
    schedule.every(30).seconds.do(run_threaded, send_heartbeat)

    # 2. 啟動(dòng)后立即運(yùn)行一次某些任務(wù)(可選)
    logger.info("啟動(dòng)后立即執(zhí)行一次清理和心跳...")
    run_threaded(cleanup_temp)
    run_threaded(send_heartbeat)

    # 3. 堅(jiān)不可摧的主循環(huán)
    while True:
        try:
            schedule.run_pending()
            # 睡眠1秒,平衡CPU使用率和調(diào)度精度
            time.sleep(1)
        except KeyboardInterrupt:
            logger.info("接收到鍵盤(pán)中斷信號(hào),正在優(yōu)雅停止調(diào)度器...")
            break
        except Exception as e:
            # 兜底:捕獲調(diào)度循環(huán)自身的任何異常,記錄并嘗試恢復(fù)
            logger.critical(f"調(diào)度器主循環(huán)發(fā)生未預(yù)期異常,將在一分鐘后重試: {e}", exc_info=True)
            time.sleep(60)

    logger.info("=== 定時(shí)任務(wù)調(diào)度器已停止 ===")

if __name__ == "__main__":
    run_scheduler()

踩坑記錄

坑:任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)導(dǎo)致調(diào)度延遲

  • 現(xiàn)象:設(shè)置每分鐘執(zhí)行的任務(wù),有時(shí)會(huì)發(fā)現(xiàn)間隔變成了1分多鐘甚至更長(zhǎng)。
  • 排查:發(fā)現(xiàn)是任務(wù)函數(shù)本身執(zhí)行耗時(shí)超過(guò)了1分鐘。schedule 會(huì)等待當(dāng)前 run_pending() 中觸發(fā)的任務(wù)函數(shù)執(zhí)行完畢,再進(jìn)入下一次循環(huán)。
  • 解決:使用 run_threaded 將每個(gè)任務(wù)放到獨(dú)立線程,確保 schedule.run_pending() 不會(huì)被阻塞。這是最關(guān)鍵的一步。

坑:任務(wù)異常導(dǎo)致整個(gè)程序退出

  • 現(xiàn)象:在任務(wù)函數(shù)里模擬一個(gè) ZeroDivisionError,整個(gè)Python腳本直接崩潰。
  • 排查:默認(rèn)情況下,線程中未捕獲的異常會(huì)導(dǎo)致線程退出,但不會(huì)影響主進(jìn)程。然而,如果是在主線程中直接調(diào)用任務(wù)函數(shù),異常就會(huì)上傳。
  • 解決:在每個(gè)任務(wù)函數(shù)內(nèi)部使用 try...except 進(jìn)行最廣泛的異常捕獲,并記錄詳細(xì)的錯(cuò)誤日志。確保異常被消化在任務(wù)內(nèi)部。

坑:日志混亂,分不清是哪個(gè)任務(wù)的輸出

  • 現(xiàn)象:所有任務(wù)的 print 語(yǔ)句都混在一起,時(shí)間久了根本不知道哪行日志對(duì)應(yīng)哪個(gè)任務(wù)。
  • 排查:使用了簡(jiǎn)單的 print,且沒(méi)有任務(wù)標(biāo)識(shí)。
  • 解決:引入 logging 模塊,為日志配置時(shí)間戳和級(jí)別。在每條任務(wù)日志中,都加入任務(wù)名稱(chēng)的標(biāo)識(shí)(如 f"[數(shù)據(jù)同步] ...")。使用 exc_info=True 記錄錯(cuò)誤堆棧。

坑:多個(gè)任務(wù)同時(shí)操作一個(gè)文件,內(nèi)容錯(cuò)亂

  • 現(xiàn)象:數(shù)據(jù)同步任務(wù)和清理任務(wù)偶爾會(huì)同時(shí)操作同一個(gè)臨時(shí)文件,導(dǎo)致文件內(nèi)容損壞或清理誤刪正在寫(xiě)入的文件。
  • 排查:線程是并發(fā)執(zhí)行的,兩個(gè)任務(wù)可能在極短時(shí)間內(nèi)先后進(jìn)入文件操作環(huán)節(jié)。
  • 解決:對(duì)于需要互斥訪問(wèn)的共享資源(文件、數(shù)據(jù)庫(kù)行、內(nèi)存變量),使用 threading.Lock 實(shí)現(xiàn)簡(jiǎn)單的互斥鎖,確保同一時(shí)間只有一個(gè)任務(wù)能操作該資源。

小結(jié)

經(jīng)過(guò)這一輪折騰,我把一個(gè)簡(jiǎn)單的 schedule 循環(huán),加固成了一個(gè)適合生產(chǎn)環(huán)境的定時(shí)任務(wù)骨架。核心收獲是:在自動(dòng)化腳本中,任何可能出錯(cuò)的地方最終都會(huì)出錯(cuò),必須用線程隔離任務(wù),用異常捕獲兜底,用清晰日志留痕。這個(gè)方案目前已經(jīng)穩(wěn)定運(yùn)行了三周,沒(méi)有再出現(xiàn)無(wú)故退出的情況。如果你有更復(fù)雜的分布式需求,這個(gè)單機(jī)方案可能不夠,那時(shí)可以考慮 APScheduler 的持久化功能或者 Celery 這樣的分布式任務(wù)隊(duì)列了。

到此這篇關(guān)于Python schedule庫(kù)實(shí)現(xiàn)定時(shí)任務(wù)的避坑指南的文章就介紹到這了,更多相關(guān)Python schedule定時(shí)任務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python 經(jīng)典算法100及解析(小結(jié))

    Python 經(jīng)典算法100及解析(小結(jié))

    這篇文章主要介紹了Python 經(jīng)典算法100及解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • matplotlib bar()實(shí)現(xiàn)多組數(shù)據(jù)并列柱狀圖通用簡(jiǎn)便創(chuàng)建方法

    matplotlib bar()實(shí)現(xiàn)多組數(shù)據(jù)并列柱狀圖通用簡(jiǎn)便創(chuàng)建方法

    這篇文章主要介紹了matplotlib bar()實(shí)現(xiàn)多組數(shù)據(jù)并列柱狀圖通用簡(jiǎn)便創(chuàng)建方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • python3中超級(jí)好用的日志模塊-loguru模塊使用詳解

    python3中超級(jí)好用的日志模塊-loguru模塊使用詳解

    loguru默認(rèn)的輸出格式是上面的內(nèi)容,有時(shí)間、級(jí)別、模塊名、行號(hào)以及日志信息,不需要手動(dòng)創(chuàng)建?logger,直接使用即可,另外其輸出還是彩色的,看起來(lái)會(huì)更加友好,這篇文章主要介紹了python3中超級(jí)好用的日志模塊-loguru模塊使用詳解,需要的朋友可以參考下
    2022-11-11
  • python sort、sorted高級(jí)排序技巧

    python sort、sorted高級(jí)排序技巧

    這篇文章主要介紹了python sort、sorted高級(jí)排序技巧,本文講解了基礎(chǔ)排序、升序和降序、排序的穩(wěn)定性和復(fù)雜排序、cmp函數(shù)排序法等內(nèi)容,需要的朋友可以參考下
    2014-11-11
  • python 快速排序代碼

    python 快速排序代碼

    閑來(lái)無(wú)事寫(xiě)了個(gè)python快排序
    2009-11-11
  • 淺析PyTorch中nn.Linear的使用

    淺析PyTorch中nn.Linear的使用

    這篇文章主要介紹了淺析PyTorch中nn.Linear的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Python MNIST手寫(xiě)體識(shí)別詳解與試練

    Python MNIST手寫(xiě)體識(shí)別詳解與試練

    MNIST(官方網(wǎng)站)是非常有名的手寫(xiě)體數(shù)字識(shí)別數(shù)據(jù)集,在Tensorflow的官方網(wǎng)站里,第一個(gè)就拿它來(lái)做實(shí)戰(zhàn)講解,咱們也以此作為開(kāi)始的項(xiàng)目
    2021-11-11
  • 用python實(shí)現(xiàn)的去除win下文本文件頭部BOM的代碼

    用python實(shí)現(xiàn)的去除win下文本文件頭部BOM的代碼

    windows環(huán)境下新建或編輯文本文件,保存時(shí)會(huì)在頭部加上BOM。使用ftp上傳到linux下,在執(zhí)行時(shí)第一行即報(bào)錯(cuò)。以下方法可以去除BOM頭,有需要的朋友可以參考下
    2013-02-02
  • Empty test suite.(PyCharm程序運(yùn)行錯(cuò)誤的解決方法)

    Empty test suite.(PyCharm程序運(yùn)行錯(cuò)誤的解決方法)

    今天小編就為大家分享一篇Empty test suite.(PyCharm程序運(yùn)行錯(cuò)誤的解決方法),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • python3實(shí)現(xiàn)繪制二維點(diǎn)圖

    python3實(shí)現(xiàn)繪制二維點(diǎn)圖

    今天小編就為大家分享一篇python3實(shí)現(xiàn)繪制二維點(diǎn)圖,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12

最新評(píng)論

府谷县| 临汾市| 河源市| 峨山| 上饶县| 河津市| 蒙山县| 马公市| 垦利县| 柏乡县| 卫辉市| 黄梅县| 上蔡县| 巴东县| 于都县| 鹿邑县| 资兴市| 仙游县| 武穴市| 哈尔滨市| 望城县| 金乡县| 三门县| 元氏县| 皋兰县| 遵义市| 丹江口市| 张家界市| 赣榆县| 金平| 冷水江市| 平度市| 张北县| 水城县| 屏南县| 二手房| 长沙市| 密云县| 中山市| 博湖县| 乡宁县|