python3使用pyinstaller打包apscheduler出的錯

Gin.p發表於2016-11-19

  本來只是想用Python做一個定時任務小工具在伺服器上執行,可是伺服器在隔離區,各種禁止上外網,使用pip匯出列表那種下載庫的方法不管用,導致Python的各種庫都下不到,官網離線下載又各種缺依賴,好氣啊。後來查了一下,原來還有pyinstaller這種好東西,將需要的庫和程式打包成一個可執行的程式,這正是我需要的。  

  為了測試pyinstaller,主要遇到了兩個錯誤,一個是pkg_resources.DistributionNotFound,一個是ImportError: No module named。下面又開始說起,需要看主要解決辦法的可以看大標題。

  先搞一個測試小程式吧,這個程式很簡單,每5s列印一次a:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from apscheduler.schedulers.blocking import BlockingScheduler


def p():
    print("a")

if __name__ == '__main__':
    scheduler = BlockingScheduler()
    scheduler.add_job(p, "cron",second='1/5')

    try:
        scheduler.start()
    except Exception as e:
        pass

使用pyinstaller打包成一個單獨可執行的檔案:

pyinstaller -F test1.py

pkg_resources.DistributionNotFound

可是出錯了,提示找不到APScheduler,可我已經下載了啊,苦悶。

Traceback (most recent call last):
  File "test1.py", line 4, in <module>
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 634, in _load_backward_compatible
  File "c:\users\fstmp\appdata\local\programs\python\python35-32\lib\site-packag
es\PyInstaller\loader\pyimod03_importers.py", line 389, in load_module
    exec(bytecode, module.__dict__)
  File "site-packages\apscheduler\__init__.py", line 2, in <module>
  File "site-packages\pkg_resources\__init__.py", line 535, in get_distribution
  File "site-packages\pkg_resources\__init__.py", line 415, in get_provider
  File "site-packages\pkg_resources\__init__.py", line 943, in require
  File "site-packages\pkg_resources\__init__.py", line 829, in resolve
pkg_resources.DistributionNotFound: The 'APScheduler' distribution was not found
 and is required by the application
Failed to execute script test1

我查了一下,官方Issues給出了答案https://github.com/pyinstaller/pyinstaller/issues/1713

大概就是建立一個hook-ctypes.macholib.py,內容是:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from PyInstaller.utils.hooks import copy_metadata

datas = copy_metadata('apscheduler')

然後打包的時候新增--additional-hooks-dir=

pyinstaller -F test1.py --additional-hooks-dir=.

可是,又出現了一個新問題ImportError: No module named

ImportError: No module named

Traceback (most recent call last):
  File "site-packages\apscheduler\schedulers\base.py", line 880, in _create_plug
in_instance
KeyError: 'cron'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test1.py", line 14, in <module>
  File "site-packages\apscheduler\schedulers\base.py", line 411, in add_job
  File "site-packages\apscheduler\schedulers\base.py", line 905, in _create_trig
ger
  File "site-packages\apscheduler\schedulers\base.py", line 883, in _create_plug
in_instance
  File "site-packages\pkg_resources\__init__.py", line 2229, in load
  File "site-packages\pkg_resources\__init__.py", line 2235, in resolve
ImportError: No module named 'apscheduler.triggers.cron'
Failed to execute script test1

pkg_resources.DistributionNotFound問題好像解決了,但又來了一個新問題ImportError: No module named

看描述好像是cron哪裡出了問題,把CronTrigger單獨新建,修正後:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger


def p():
    print("a")

if __name__ == '__main__':
    scheduler = BlockingScheduler()
    trigger = CronTrigger(second='1/5')
    scheduler.add_job(p, trigger)

    try:
        scheduler.start()
    except Exception as e:
        pass

經過上面修改後,應該可以正常執行了。如果你也有這樣的問題,看看我的經驗能不能幫到你?

相關文章