iT邦幫忙

0

python 特定時間執行會有問題

  • 分享至 

  • xImage

小弟我有一支python程式每三小時會執行一次,網路撈資料並產生檔案,但只要在晚上22點執行撈19-22的資料就會失敗。
先上程式碼
1.先判定時間區間

from datetime import datetime, timedelta

current_time = datetime.now()
time_ranges = [
    (7, 10),
    (10, 13),
    (13, 16),
    (16, 19),
    (19, 22),
    (22, 1),
    (1, 4),
    (4, 7)
]

a = current_time.strftime("%Y-%m-%d %H:%M:%S")
file_name = ""

# 目前時間比對時間範圍
for start_hour, end_hour in time_ranges:
    start_time = current_time.replace(hour=start_hour, minute=0, second=0, microsecond=0)
    end_time = current_time.replace(hour=end_hour, minute=0, second=0, microsecond=0)

    if start_hour > end_hour:
        if current_time.hour < start_hour:
            end_time += timedelta(days=-1)  # 當前時間在第二天的時間範圍內
        else:
            end_time += timedelta(days=1)  # 當前時間在第一天的時間範圍內
#檔名命名
    if start_time <= current_time < end_time:
        start_time -= timedelta(hours=3)
        end_time -= timedelta(hours=3)
        file_name = (
            start_time.strftime("%Y-%m-%d-%H-%M-%S") + "-"
            + end_time.strftime("%Y-%m-%d-%H-%M-%S") + ".xlsx"
        )
        break

print("檔案名稱:", file_name)

2.到網頁撈時間區間內的資料

start_time = current_time.replace(hour=start_hour, minute=0, second=0, microsecond=0)
            end_time = current_time.replace(hour=end_hour, minute=0, second=0, microsecond=0)
            specific_date = datetime.datetime(1970, 1, 1, 0, 0, 0)
            # 因為時差要先-11小時
            start_time = start_time - datetime.timedelta(hours=11)
            end_time = end_time - datetime.timedelta(hours=11)
            
            # print(start_time,end_time)
            # 计算时间差
            start_time = start_time - specific_date
            end_time = end_time - specific_date
            # 获取时间差的总秒数
            start_time = int(start_time.total_seconds())
            end_time = int(end_time.total_seconds())
            # print(start_time,end_time)
            try:
                url_string=f'http://{ip}:9999/api/detection/ex?start_time={start_time}&end_time={end_time}&result=ALL'
                # print(url_string)
            except:
                print('有問題')

3.正常的數值
1704355200-1704366000
失敗的數值
1704279600-1704204000
->前面的數值是正確的 但後面的1704204000會固定出現(不是我要的)

目前檔案產生都正常,名稱也正確,網頁都有正常運作,但在晚上22點就是撈不到資料。

第一次發問,若缺少可判斷的資訊請再跟我說。
排版混亂也請見諒。

附上log
正常

Jan  3 19:05:01 mis-pyserver CRON[4856]: (mis) CMD (    python3.10 /home/mis/Desktop/py/ccd_top3_bad_report_day/top3.py)
Jan  3 19:14:12 mis-pyserver postfix/pickup[4641]: B2A99260630: uid=1000 from=<mis>
Jan  3 19:14:12 mis-pyserver postfix/cleanup[5052]: B2A99260630: message-id=<20240103111412.B2A99260630@mis-pyserver>
Jan  3 19:14:12 mis-pyserver postfix/qmgr[1621]: B2A99260630: from=<mis@mis-pyserver>, size=84592, nrcpt=1 (queue active)
Jan  3 19:14:12 mis-pyserver postfix/local[5054]: B2A99260630: to=<mis@mis-pyserver>, orig_to=<mis>, relay=local, delay=0.05, delays=0.04/0.01/0/0, dsn=2.0.0, status=sent (delivered to m>
Jan  3 19:14:12 mis-pyserver postfix/qmgr[1621]: B2A99260630: removed

失敗

Jan  3 22:05:01 mis-pyserver CRON[5159]: (mis) CMD (    python3.10 /home/mis/Desktop/py/ccd_top3_bad_report_day/top3.py)
Jan  3 22:07:15 mis-pyserver postfix/pickup[5154]: 2520B260630: uid=1000 from=<mis>
Jan  3 22:07:15 mis-pyserver postfix/cleanup[5354]: 2520B2`�=`�=a�>60630: message-id=<20240103140715.2520B260630@mis-pyserver>
Jan  3 22:07:15 mis-pyserver postfix/qmgr[1621]: 2520B260630: from=<mis@mis-pyserver>, size=19139, nrcpt=1 (queue active)
Jan  3 22:07:15 mis-pyserver postfix/local[5356]: 2520B260630: to=<mis@mis-pyserver>, orig_to=<mis>, relay=local, delay=0.08, delays=0.06/0.01/0/0.01, dsn=2.0.0, status=sent (delivered t>
Jan  3 22:07:15 mis-pyserver postfix/qmgr[1621]: 2520B260630: removed

看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2024-01-05 12:36:19 檢舉
沒看到啥問題,或許要到執行環境看,不過有幾點要說的
1. 你的哪兩串數字是timestamp,根本不需要你自己減
2. timestamp不會跟著時區變動,只要時間正確,在哪台電腦都一樣
https://ideone.com/FaGCh9
ccutmis iT邦高手 2 級 ‧ 2024-01-05 12:40:45 檢舉
可以換個思路,每天固定時間執行不要在python處理改由系統提供的程式來處理。例如 Windows 的 工作排程器 或 Linux 的 crontab ,(你可以搜'工作排程器 執行python'網路上有很多教學),時間到了就會執行你的python腳本,而python腳本只需要爬資料。
abian9895 iT邦新手 5 級 ‧ 2024-01-05 13:12:10 檢舉
cc大,目前是在linux上用crontab運作沒錯,指令為0 1-23/3 * * *,其他時間都正常,就只有19-22會出狀況。
ccutmis iT邦高手 2 級 ‧ 2024-01-05 13:34:16 檢舉
我想一下再回覆xD
abian9895 iT邦新手 5 級 ‧ 2024-01-05 13:38:05 檢舉
froce大,感謝你,我會再做嘗試的!!
abian9895 iT邦新手 5 級 ‧ 2024-01-05 13:45:44 檢舉
CC大,程式中有寫log紀錄有沒有讀取到,但因為timestamp是錯誤的所以被判定成無資料,實際上是有資料的,最奇怪的就是只有那個時間段會這樣...
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
ccutmis
iT邦高手 2 級 ‧ 2024-01-05 15:03:22
最佳解答

from datetime import datetime
import time

# 取得當下日期時間字串,例如: "2023-03-20-22-30-00"
def get_now_datetime_str():
    now = datetime.now()
    return now.strftime("%Y-%m-%d-%H-%M-%S")

# 將字串 "2023-03-20-22-30-00" 轉為 timestamp "1679359553051"
def datetime_str_to_timestamp(s):
    #s = "2023-03-20-22-30-00"
    return int(time.mktime(datetime.strptime(s, "%Y-%m-%d-%H-%M-%S").timetuple()))

# 將 timestamp 轉為 日期時間
def timestamp_to_datetime(st):
    #st = "1679359553051"
    return datetime.fromtimestamp(st)

current_time_str = get_now_datetime_str()
# print(current_time_str)

end_time_str = current_time_str[:11]+current_time_str[11:13]+'-00-00'
end_time = datetime_str_to_timestamp(end_time_str)

start_time = end_time -(60*60*3)
start_time_str = timestamp_to_datetime(start_time).strftime("%Y-%m-%d-%H-%M-%S")

print('start_time',start_time,start_time_str)
print('end_time',end_time,end_time_str)

file_name=f"{start_time_str}-{end_time_str}.xlsx"
print("檔案名稱:", file_name)

ip ='1.2.3.4'
url_string=f'http://{ip}:9999/api/detection/ex?start_time={start_time}&end_time={end_time}&result=ALL'
print(url_string)

Output:

start_time 1704423600 2024-01-05-11-00-00
end_time 1704434400 2024-01-05-14-00-00
檔案名稱: 2024-01-05-11-00-00-2024-01-05-14-00-00.xlsx
http://1.2.3.4:9999/api/detection/ex?start_time=1704423600&end_time=1704434400&result=ALL

本文的回覆貼源碼沒法縮進,只好貼在回答區了。
控制何時執行python腳本的部份依樓主描述應該是沒問題,那麼問題就出在timestamp的部份,我這邊用一個笨方法給您參考,大概邏輯是這樣的:

  1. 取得程式執行時的時間字串,例如:2024-01-05-14-20-30
  2. 取得的時間字串把分跟秒用'00'取代,然後轉成 timestamp (end_time)
  3. 計算 start_time (即為 end_time 減 三小時的秒數 60x60x3)
  4. 把 start_time 轉成時間字串
  5. 至此需要的 timestamp 跟 時間字串就有了,另外樓主有提到因為時差要修正的地方,同步驟3的原理對 start_time 及 end_time 同時加或減修正的秒數即可,理論上可行,你先試試看有問題再討論。
  6. 不知道你撈的是什麼數據,有另一種可能是,換資料的那個時間段就是撈不到,例如有的資料源每天固定一個時間維護,你的程式剛好在那時間裡執行,這只是猜的,假如你的排程跟腳本確實沒問題的話…。
看更多先前的回應...收起先前的回應...
froce iT邦大師 1 級 ‧ 2024-01-05 15:31:17 檢舉

不需要這麼麻煩啦,前面給他的程式碼改一下就能抓到執行時整點往前3小時的資料了。
然後timestamp是目標時間到1970 1/1 0:00:00的時間,這都是用UTC算的,不會有機器的時區問題。
搭配cron就可以做到執行時直接去找3小時前的資料,不需要用到字串去轉...

ccutmis iT邦高手 2 級 ‧ 2024-01-05 15:32:37 檢舉

好象是耶,ㄏㄏ

abian9895 iT邦新手 5 級 ‧ 2024-01-05 16:12:17 檢舉

目前已將程式碼修改成用timestamp取得數值的方式,但要等到22點實測後才能曉得問題有沒有改善。感謝兩位大大的幫助。

abian9895 iT邦新手 5 級 ‧ 2024-01-08 09:09:28 檢舉

兩位大大,可以順利撈出19-22時間段的資料了,非常感謝!

ccutmis iT邦高手 2 級 ‧ 2024-01-08 12:55:20 檢舉

/images/emoticon/emoticon42.gif

我要發表回答

立即登入回答