子流程的特定时间会产生不良结果
Specific timing of a subprocess yields undesireable results
我的目标是让此脚本 运行 在远程计算机上,并在 'specific' 的时间,每小时执行一次子进程(一次)。脚本 运行 按预期执行,直到 运行 子进程的时间到了。它不是一次执行一个文件,而是 运行 不停地执行所有文件。我也尝试过使用不同的睡眠时间来打破循环,但无济于事。
这是脚本:
import time
import os
import subprocess
print("Waiting To Upload File ... ")
PATH = r'C:\Users\trcyp\Documents\PythonExample'
while True:
r = time.localtime()
m = r.tm_min
s = r.tm_sec
if m == 43 and s == 0: #I want to run the script below at this specific min/sec.
for root, subFolder, files in os.walk(PATH):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("This is where my subprocess would be")
#os.remove(fileNamePath)
print("Upload Successful, " + time.asctime())
time.sleep(1)
else:
print("Current m/s", m, ':', s, "\r", end="")
time.sleep(1)
这是我的输出:
Waiting To Upload File ...
Uploading: C:\Users\trcyp\Documents\PythonExample\CustomLoadSheet.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:00 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\Default.aspx.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:01 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\DeliveryDetail(2).pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:02 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\DeliveryDetail.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:03 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\ESP8266ModuleV1.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:04 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\track.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:05 2021
Current m/s 43 : 19
我已经使用了多种配置,但我仍然卡住了。脚本的原始 () 版本运行良好,但使用 time.sleep()
导致执行子流程的时间全天候缓慢移动。我正在尝试一次 运行 一个文件,每次都在同一时间。
按照@VpFB 的建议,您尝试计算等待时间:
import time
import os
import subprocess
import datetime
def get_next(minute, second):
now = datetime.datetime.now()
next_time_args = dict(year=now.year, month=now.month, day=now.day,
hour=now.hour+1, minute=minute, second=second)
return datetime.datetime(**next_time_args)
def wait_till_next(next_time):
now = datetime.datetime()
seconds = (next_time-now).microseconds / 1e6 # 1e6microsecond=1s
if seconds>0:
time.sleep(seconds)
print("Waiting To Upload File ... ")
PATH = r'C:\Users\trcyp\Documents\PythonExample'
next_time = None
waited = False # this makes sure you upload the next hour's file even if your previous upload took more more than an hour but less than two hours.
while True:
r = time.localtime()
m = r.tm_min
s = r.tm_sec
next_time = get_next(minute=43, second=0)
if waited or (m == 43 and s == 0): #I want to run the script below at this specific min/sec.
for root, subFolder, files in os.walk(PATH):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("This is where my subprocess would be")
#os.remove(fileNamePath)
print("Upload Successful, " + time.asctime())
time.sleep(1)
else:
print("Current m/s", m, ':', s, "\r", end="")
wait_till_next(next_time)
waited = True
包 apscheduler
基本上在 python 脚本中为您提供 cron
。以下是您的脚本示例,运行在小时后 43 分钟执行计划任务:
import apscheduler
import os
from datetime import datetime
import time
import subprocess
from apscheduler.schedulers.background import BackgroundScheduler
def make_generator_func_callable(gen_func):
# a decorator that makes generators callable so they can be used with scheduler
task_generator = gen_func()
def callable_generator():
try:
return next(task_generator)
except StopIteration:
print("(nothing left to do)")
return callable_generator
@make_generator_func_callable
def my_task(path=PATH):
for root, subFolder, files in os.walk(path):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("This is where my subprocess would be")
#os.remove(fileNamePath)
print("Upload Successful, " + time.asctime())
#time.sleep(1)
yield
@make_generator_func_callable
def test_task():
for item in [1,2,3]:
print(datetime.now())
print(item)
yield
if __name__ == "__main__":
print("Waiting To Upload File ... ")
# start scheduler as a background/non-blocking process
scheduler = BackgroundScheduler()
scheduler.start()
# your cron-style task. This is also an "interval" option
# scheduler.add_job(my_task, "cron", minute="43", id='my_job')
scheduler.add_job(test_task, "interval", seconds=3, id='test_job')
# this is a blocking prompt to prevent your script from exiting
ans = input("press return to shutdown the script")
scheduler.shutdown()
为什么要使用专用的调度程序包?安排任务并不完全是微不足道的,并且从专用的后台进程中受益匪浅。如果您尝试“自己动手”,您可能 运行 遇到以下任何问题:
- 作业因完成速度快而意外提交多次
- jobs missed/skipped 因为您的进程在需要的时间忙于做其他事情
- 作业失败并阻止您的代码继续
相比之下,apscheduler
为您解决所有这些困难,并在您需要时提供更高级的功能(跨会话的作业持久性等)
请注意,修改后的脚本会将您的脚本转换为生成器函数(然后将其包装为可调用)。这可能不是最优雅的解决方案,但可以通过最少的修改完成工作
正如评论中所讨论的那样,这里是一个睡眠时间计算示例,该任务在给定的分钟和秒内每小时重复一次。
import datetime as dt
def get_sleeptime(minute, second):
"""Return seconds from now till nearest *:min:sec time"""
now = dt.datetime.now()
sched = now.replace(minute=minute, second=second, microsecond=0)
sleeptime = (sched - now).total_seconds() # the difference is a timedelta object
if sleeptime < 0:
sleeptime += 3600
return sleeptime
print(get_sleeptime(43,0) # test
我认为它在主循环中的用法很清楚。
好的。因此,在研究和测试所有建议和答案之后,@VPfB 的最新答案最容易集成到我现有的脚本中。我只是想 post 在这里供其他希望使用它或做类似事情的人使用。我唯一需要做的是在结束时放置 1 秒的睡眠,但在 get_sleeptime
调用之前打破循环足够长的时间让计时器接管。到目前为止它运行完美。这是最终产品...
import datetime as dt
import time
import os
import subprocess
PATH = '/home/pi/Public/'
def get_sleeptime(minute, second):
now = dt.datetime.now()
sched = now.replace(minute=minute, second=second)
sleeptime = (sched - now).total_seconds() # the difference is a timedelta object
if sleeptime < 0:
sleeptime += 3600
return sleeptime
for root, subFolder, files in os.walk(PATH):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("")
subprocess.run(['telegram-upload', '-d', '-f', 'file_dumpster', str(fileNamePath)])
print("")
print("Upload Successful >> " + time.asctime())
print("")
time.sleep(1) #added to break loop long just long enough
print(" <<... Waiting To Upload New File ...>> ")
time.sleep(get_sleeptime(11, 0)) #set at 11 minutes past the hour
这是输出...
Uploading: C:\Users\trcyp\Documents\PythonExample\New Text Document - Copy (2).txt
This is where my subprocess would be
Upload Successful >> Mon Feb 22 19:10:26 2021 #initial file upload
<<... Waiting To Upload New File ...>>
Uploading: C:\Users\trcyp\Documents\PythonExample\New Text Document - Copy (3).txt
This is where my subprocess would be
Upload Successful >> Mon Feb 22 19:11:00 2021 #11 minutes past the hour
<<... Waiting To Upload New File ...>>
Uploading: C:\Users\trcyp\Documents\PythonExample\New Text Document - Copy (4).txt
This is where my subprocess would be
Upload Successful >> Mon Feb 22 20:11:00 2021 #11 minutes past the hour
<<... Waiting To Upload New File ...>>
我的目标是让此脚本 运行 在远程计算机上,并在 'specific' 的时间,每小时执行一次子进程(一次)。脚本 运行 按预期执行,直到 运行 子进程的时间到了。它不是一次执行一个文件,而是 运行 不停地执行所有文件。我也尝试过使用不同的睡眠时间来打破循环,但无济于事。 这是脚本:
import time
import os
import subprocess
print("Waiting To Upload File ... ")
PATH = r'C:\Users\trcyp\Documents\PythonExample'
while True:
r = time.localtime()
m = r.tm_min
s = r.tm_sec
if m == 43 and s == 0: #I want to run the script below at this specific min/sec.
for root, subFolder, files in os.walk(PATH):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("This is where my subprocess would be")
#os.remove(fileNamePath)
print("Upload Successful, " + time.asctime())
time.sleep(1)
else:
print("Current m/s", m, ':', s, "\r", end="")
time.sleep(1)
这是我的输出:
Waiting To Upload File ...
Uploading: C:\Users\trcyp\Documents\PythonExample\CustomLoadSheet.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:00 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\Default.aspx.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:01 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\DeliveryDetail(2).pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:02 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\DeliveryDetail.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:03 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\ESP8266ModuleV1.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:04 2021
Uploading: C:\Users\trcyp\Documents\PythonExample\track.pdf
This is where my subprocess would be
Upload Successful, Sun Feb 21 11:43:05 2021
Current m/s 43 : 19
我已经使用了多种配置,但我仍然卡住了。脚本的原始 (time.sleep()
导致执行子流程的时间全天候缓慢移动。我正在尝试一次 运行 一个文件,每次都在同一时间。
按照@VpFB 的建议,您尝试计算等待时间:
import time
import os
import subprocess
import datetime
def get_next(minute, second):
now = datetime.datetime.now()
next_time_args = dict(year=now.year, month=now.month, day=now.day,
hour=now.hour+1, minute=minute, second=second)
return datetime.datetime(**next_time_args)
def wait_till_next(next_time):
now = datetime.datetime()
seconds = (next_time-now).microseconds / 1e6 # 1e6microsecond=1s
if seconds>0:
time.sleep(seconds)
print("Waiting To Upload File ... ")
PATH = r'C:\Users\trcyp\Documents\PythonExample'
next_time = None
waited = False # this makes sure you upload the next hour's file even if your previous upload took more more than an hour but less than two hours.
while True:
r = time.localtime()
m = r.tm_min
s = r.tm_sec
next_time = get_next(minute=43, second=0)
if waited or (m == 43 and s == 0): #I want to run the script below at this specific min/sec.
for root, subFolder, files in os.walk(PATH):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("This is where my subprocess would be")
#os.remove(fileNamePath)
print("Upload Successful, " + time.asctime())
time.sleep(1)
else:
print("Current m/s", m, ':', s, "\r", end="")
wait_till_next(next_time)
waited = True
包 apscheduler
基本上在 python 脚本中为您提供 cron
。以下是您的脚本示例,运行在小时后 43 分钟执行计划任务:
import apscheduler
import os
from datetime import datetime
import time
import subprocess
from apscheduler.schedulers.background import BackgroundScheduler
def make_generator_func_callable(gen_func):
# a decorator that makes generators callable so they can be used with scheduler
task_generator = gen_func()
def callable_generator():
try:
return next(task_generator)
except StopIteration:
print("(nothing left to do)")
return callable_generator
@make_generator_func_callable
def my_task(path=PATH):
for root, subFolder, files in os.walk(path):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("This is where my subprocess would be")
#os.remove(fileNamePath)
print("Upload Successful, " + time.asctime())
#time.sleep(1)
yield
@make_generator_func_callable
def test_task():
for item in [1,2,3]:
print(datetime.now())
print(item)
yield
if __name__ == "__main__":
print("Waiting To Upload File ... ")
# start scheduler as a background/non-blocking process
scheduler = BackgroundScheduler()
scheduler.start()
# your cron-style task. This is also an "interval" option
# scheduler.add_job(my_task, "cron", minute="43", id='my_job')
scheduler.add_job(test_task, "interval", seconds=3, id='test_job')
# this is a blocking prompt to prevent your script from exiting
ans = input("press return to shutdown the script")
scheduler.shutdown()
为什么要使用专用的调度程序包?安排任务并不完全是微不足道的,并且从专用的后台进程中受益匪浅。如果您尝试“自己动手”,您可能 运行 遇到以下任何问题:
- 作业因完成速度快而意外提交多次
- jobs missed/skipped 因为您的进程在需要的时间忙于做其他事情
- 作业失败并阻止您的代码继续
相比之下,apscheduler
为您解决所有这些困难,并在您需要时提供更高级的功能(跨会话的作业持久性等)
请注意,修改后的脚本会将您的脚本转换为生成器函数(然后将其包装为可调用)。这可能不是最优雅的解决方案,但可以通过最少的修改完成工作
正如评论中所讨论的那样,这里是一个睡眠时间计算示例,该任务在给定的分钟和秒内每小时重复一次。
import datetime as dt
def get_sleeptime(minute, second):
"""Return seconds from now till nearest *:min:sec time"""
now = dt.datetime.now()
sched = now.replace(minute=minute, second=second, microsecond=0)
sleeptime = (sched - now).total_seconds() # the difference is a timedelta object
if sleeptime < 0:
sleeptime += 3600
return sleeptime
print(get_sleeptime(43,0) # test
我认为它在主循环中的用法很清楚。
好的。因此,在研究和测试所有建议和答案之后,@VPfB 的最新答案最容易集成到我现有的脚本中。我只是想 post 在这里供其他希望使用它或做类似事情的人使用。我唯一需要做的是在结束时放置 1 秒的睡眠,但在 get_sleeptime
调用之前打破循环足够长的时间让计时器接管。到目前为止它运行完美。这是最终产品...
import datetime as dt
import time
import os
import subprocess
PATH = '/home/pi/Public/'
def get_sleeptime(minute, second):
now = dt.datetime.now()
sched = now.replace(minute=minute, second=second)
sleeptime = (sched - now).total_seconds() # the difference is a timedelta object
if sleeptime < 0:
sleeptime += 3600
return sleeptime
for root, subFolder, files in os.walk(PATH):
files.sort(key=str.lower)
subFolder.sort()
for item in files:
fileNamePath = os.path.join(root, item)
print("Uploading: " + fileNamePath)
print("")
subprocess.run(['telegram-upload', '-d', '-f', 'file_dumpster', str(fileNamePath)])
print("")
print("Upload Successful >> " + time.asctime())
print("")
time.sleep(1) #added to break loop long just long enough
print(" <<... Waiting To Upload New File ...>> ")
time.sleep(get_sleeptime(11, 0)) #set at 11 minutes past the hour
这是输出...
Uploading: C:\Users\trcyp\Documents\PythonExample\New Text Document - Copy (2).txt
This is where my subprocess would be
Upload Successful >> Mon Feb 22 19:10:26 2021 #initial file upload
<<... Waiting To Upload New File ...>>
Uploading: C:\Users\trcyp\Documents\PythonExample\New Text Document - Copy (3).txt
This is where my subprocess would be
Upload Successful >> Mon Feb 22 19:11:00 2021 #11 minutes past the hour
<<... Waiting To Upload New File ...>>
Uploading: C:\Users\trcyp\Documents\PythonExample\New Text Document - Copy (4).txt
This is where my subprocess would be
Upload Successful >> Mon Feb 22 20:11:00 2021 #11 minutes past the hour
<<... Waiting To Upload New File ...>>