Pythonソース学習Schedule
17828 ワード
私のプログラミング界の小さなプログラム猿について、現在、創業チームでteam leadを務めています.テクノロジースタックはAndroid、Python、Java、Goに関連しています.これも私たちのチームの主なテクノロジースタックです.連絡先:[email protected]
前回は簡単な
0 x 00準備
プロジェクトアドレス
github.com/dbader/sche…
コード
環境
0 x 01使用法
これは前編でも紹介しましたが、とても簡単です
このライブラリのドキュメントも詳しく、schedule.readthedocs.io/ライブラリの概要を参照できます.
0 x 02プロジェクト構造 を理解することができます. 0x03 schedule
scheduleソース
以下は
次に、ログ印刷ツールのインスタンスを定義します.
次に,このモジュールを定義した3つの異常クラスの構造体系は,
スケジューラの継続的な実行を取り消す
例えば、この
次に、このライブラリの2つのコアクラス
この2つのクラスはこのライブラリのコアであり、後で詳細な分析も見られます.次に、デフォルトスケジューラ
初期化を実行すると、スケジューラは空のタスクリストを作成します.
ファイルの最後にチェーン呼び出しの方法を定義し、使用するのも非常に人間的で、学ぶ価値があります.ここでの方法は、モジュールの下に定義され、
入口メソッド
だから私たちは
この方法では、まず
このとき、
まず、
ここではまず
この方法は
ここでは、タスク
主に間隔時間構成,実行する方法,スケジューラの各種時間単位などを初期化した.
時間単位が設定されており、この設定秒には、もちろん他の類似の属性方法
最後に
ここでは、
それから
ここでタスク
0 x 04まとめて
0 x 05学習資料 github.com/dbader/sche… schedule.readthedocs.io
転載先:https://juejin.im/post/5d2c7f286fb9a07ef161b444
前回は簡単な
Python
スケジューラの使用を紹介しましたが、その後、ソースコードをめくってみると、コアライブラリが1つのファイルしかなく、コード量が700行未満であることに驚きました.これは絶好の学習材料です.私を喜ばせたのは、このライブラリの作者が最近読んだ本「Python Tricks」の作者だったことだ.今、大神の実現構想を見てみましょう.0 x 00準備
プロジェクトアドレス
github.com/dbader/sche…
コード
checkout
をローカルに環境
PyCharm+venv+Python3
0 x 01使用法
これは前編でも紹介しましたが、とても簡単です
import schedule
#
def job():
print("a simple scheduler in python.")
# , 2
schedule.every(2).seconds.do(job)
if __name__ == '__main__':
while True:
schedule.run_pending()
#
a simple scheduler in python.
a simple scheduler in python.
a simple scheduler in python.
...
このライブラリのドキュメントも詳しく、schedule.readthedocs.io/ライブラリの概要を参照できます.
0 x 02プロジェクト構造
(venv) ➜ schedule git:(master) tree -L 2
.
...
├── requirements-dev.txt
├── schedule
│ └── __init__.py
├── setup.py
├── test_schedule.py
├── tox.ini
└── venv
├── bin
├── include
├── lib
├── pip-selfcheck.json
└── pyvenv.cfg
8 directories, 18 files
schedule
ディレクトリの下に__init__.py
ファイルがあります.これは私たちが重点的に学ぶ必要がある場所です.setup.py
ファイルはパブリッシュプロジェクトのプロファイルtest_schedule.py
はユニットテストファイルで、最初はドキュメントを見る以外に、ユニットテストから着手して、このライブラリの使用requirements-dev.txt
開発環境の依存ライブラリファイルは、コアのライブラリがサードパーティの依存を必要としない場合、ユニットテストはvenv
は私checkout
の後に作成されたもので、元のプロジェクトはありません__init__.py
はPython
パッケージを定義するために必要なファイルであることを知っています.このファイルで定義するメソッド、クラスは、import
コマンドを使用するときにプロジェクトにインポートし、使用できます.scheduleソース
以下は
schedule
で使用されるモジュールであり、いずれもPython
内部のモジュールである.import collections
import datetime
import functools
import logging
import random
import re
import time
logger = logging.getLogger('schedule')
次に、ログ印刷ツールのインスタンスを定義します.
次に,このモジュールを定義した3つの異常クラスの構造体系は,
Exception
から派生し,ScheduleError
,ScheduleValueError
およびIntervalError
である.class ScheduleError(Exception):
"""Base schedule exception"""
pass
class ScheduleValueError(ScheduleError):
"""Base schedule value error"""
pass
class IntervalError(ScheduleValueError):
"""An improper interval was used"""
pass
スケジューラの継続的な実行を取り消す
CancelJob
クラスも定義されています.class CancelJob(object):
"""
Can be returned from a job to unschedule itself.
"""
pass
例えば、この
CancelJob
クラスをカスタマイズされたスケジューリング方法で返すことで、使い捨てのタスクを実現することができる.#
def job():
print("a simple scheduler in python.")
# CancelJob
return schedule.CancelJob
次に、このライブラリの2つのコアクラス
Scheduler
とJob
です.class Scheduler(object):
"""
Objects instantiated by the :class:`Scheduler ` are
factories to create jobs, keep record of scheduled jobs and
handle their execution.
" ""
class Job(object):
"""
A periodic job as used by :class:`Scheduler`.
:param interval: A quantity of a certain time unit
:param scheduler: The :class:`Scheduler ` instance that
this job will register itself with once it has
been fully configured in :meth:`Job.do()`.
Every job runs at a given fixed time interval that is defined by:
* a :meth:`time unit `
* a quantity of `time units` defined by `interval`
A job is usually created and returned by :meth:`Scheduler.every`
method, which also defines its `interval`.
" ""
Scheduler
はスケジューラの実装クラスであり、スケジューラタスク(job
)の作成と実行を担当します.Job
は、タスクを実行する必要がある抽象である.この2つのクラスはこのライブラリのコアであり、後で詳細な分析も見られます.次に、デフォルトスケジューラ
default_scheduler
とタスクリストjobs
の作成です.# The following methods are shortcuts for not having to
# create a Scheduler instance:
#: Default :class:`Scheduler ` object
default_scheduler = Scheduler()
#: Default :class:`Jobs ` list
jobs = default_scheduler.jobs # todo: should this be a copy, e.g. jobs()?
import schedule
を実行すると、デフォルトでdefault_scheduler
が作成されます.Scheduler
の構造方法はdef __init__(self):
self.jobs = []
初期化を実行すると、スケジューラは空のタスクリストを作成します.
ファイルの最後にチェーン呼び出しの方法を定義し、使用するのも非常に人間的で、学ぶ価値があります.ここでの方法は、モジュールの下に定義され、
default_scheduler
インスタンスがカプセル化された呼び出しである.def every(interval=1):
"""Calls :meth:`every ` on the
:data:`default scheduler instance `.
" ""
return default_scheduler.every(interval)
def run_pending():
"""Calls :meth:`run_pending ` on the
:data:`default scheduler instance `.
" ""
default_scheduler.run_pending()
def run_all(delay_seconds=0):
"""Calls :meth:`run_all ` on the
:data:`default scheduler instance `.
" ""
default_scheduler.run_all(delay_seconds=delay_seconds)
def clear(tag=None):
"""Calls :meth:`clear ` on the
:data:`default scheduler instance `.
" ""
default_scheduler.clear(tag)
def cancel_job(job):
"""Calls :meth:`cancel_job ` on the
:data:`default scheduler instance `.
" ""
default_scheduler.cancel_job(job)
def next_run():
"""Calls :meth:`next_run ` on the
:data:`default scheduler instance `.
" ""
return default_scheduler.next_run
def idle_seconds():
"""Calls :meth:`idle_seconds ` on the
:data:`default scheduler instance `.
" ""
return default_scheduler.idle_seconds
入口メソッド
run_pending()
を参照すると、本明細書の冒頭のDemo
から、これがスケジューラを起動する方法であることが分かる.ここでは、default_scheduler
のメソッドを実行します.default_scheduler.run_pending()
だから私たちは
Scheduler
類の相応の方法に目を向けましたdef run_pending(self):
"""
Run all jobs that are scheduled to run.
Please note that it is *intended behavior that run_pending()
does not run missed jobs*. For example, if you've registered a job
that should run every minute and you only call run_pending()
in one hour increments then your job won't be run 60 times in
between but only once.
"""
runnable_jobs = (job for job in self.jobs if job.should_run)
for job in sorted(runnable_jobs):
self._run_job(job)
この方法では、まず
jobs
リストから実行する必要があるタスクをフィルタリングしてrunnable_jobs
リストに配置し、それをソートして内部の_run_job(job)
方法を順次実行する.def _run_job(self, job):
ret = job.run()
if isinstance(ret, CancelJob) or ret is CancelJob:
self.cancel_job(job)
_run_job
メソッドではjob
クラスのrun
メソッドが呼び出され、戻り値に基づいてタスクのキャンセルが必要かどうかを判断します.このとき、
Job
クラスの実装ロジックを見てみましょう.まず、
Job
がいつ作成されたかを見てみましょう.やはりDemo
のコードからschedule.every(2).seconds.do(job)
ここではまず
schedule.every()
メソッドを実行したdef every(interval=1):
"""Calls :meth:`every ` on the
:data:`default scheduler instance `.
"""
return default_scheduler.every(interval)
この方法は
scheduler
クラスのevery
メソッドですdef every(self, interval=1):
"""
Schedule a new periodic job.
:param interval: A quantity of a certain time unit
:return: An unconfigured :class:`Job `
"""
job = Job(interval, self)
return job
ここでは、タスク
job
が作成され、パラメータinterval
およびscheduler
インスタンスが構築方法に転送され、最後にjob
インスタンスがチェーン呼び出しを実現するために返される.Job
にジャンプする構造方法def __init__(self, interval, scheduler=None):
self.interval = interval # pause interval * unit between runs
self.latest = None # upper limit to the interval
self.job_func = None # the job job_func to run
self.unit = None # time units, e.g. 'minutes', 'hours', ...
self.at_time = None # optional time at which this job runs
self.last_run = None # datetime of the last run
self.next_run = None # datetime of the next run
self.period = None # timedelta between runs, only valid for
self.start_day = None # Specific day of the week to start on
self.tags = set() # unique set of tags for the job
self.scheduler = scheduler # scheduler to register with
主に間隔時間構成,実行する方法,スケジューラの各種時間単位などを初期化した.
every
メソッドを実行した後、seconds
というプロパティメソッドが呼び出されました.@property
def seconds(self):
self.unit = 'seconds'
return self
時間単位が設定されており、この設定秒には、もちろん他の類似の属性方法
minutes
、hours
、days
などがある.最後に
do
メソッドを実行しましたdef do(self, job_func, *args, **kwargs):
"""
Specifies the job_func that should be called every time the
job runs.
Any additional arguments are passed on to job_func when
the job runs.
:param job_func: The function to be scheduled
:return: The invoked job instance
"""
self.job_func = functools.partial(job_func, *args, **kwargs)
try:
functools.update_wrapper(self.job_func, job_func)
except AttributeError:
# job_funcs already wrapped by functools.partial won't have
# __name__, __module__ or __doc__ and the update_wrapper()
# call will fail.
pass
self._schedule_next_run()
self.scheduler.jobs.append(self)
return self
ここでは、
functools
ツールのバイアス関数partial
を使用して、カスタマイズした方法を呼び出し可能なオブジェクトにカプセル化します.それから
_schedule_next_run
方法を呼び出して、それは主に時間に対する解析で、時間によってjob
を並べ替えて、私はこの方法が本プロジェクトの中の技術点だと思って、論理も少し複雑でなくして、よく読んで理解することができて、主に時間datetime
の使用に対してです.紙面のため、ここにはコードが貼られません.ここでタスク
job
の追加を完了します.その後、run_pending
メソッドを呼び出すと、タスクを実行できます.0 x 04まとめて
schedule
ライブラリは、2つのコアクラスScheduler
およびJob
を定義します.パッケージをインポートすると、デフォルトでScheduler
オブジェクトが作成され、タスクリストが初期化されます.schedule
モジュールはチェーン呼び出しのインタフェースを提供し、schedule
パラメータを構成すると、タスクオブジェクトjob
が作成され、job
がタスクリストに追加され、最後にrun_pending
メソッドを実行すると、カスタムメソッドが呼び出されます.このライブラリの核心思想は対象向けの方法を使用して、物事に対して正確に抽象することができて、その全体の論理は複雑ではありませんて、ソースコードを学ぶのはとても良い例です.0 x 05学習資料
転載先:https://juejin.im/post/5d2c7f286fb9a07ef161b444