Search code examples
pythonpython-schedule

TypeError: the first argument must be callable - self.job_func = functools.partial(job_func, *args, **kwargs)


I seem to be experiencing an issue with the following Python Scheduler tasks. I have the below code which has a function to refresh all workbooks in a set bunch of directories. I have attempted to test the code only refreshing the one directory before moving onto the others and I am receiving the titled error. Is anyone able to help?

import time
import schedule
import win32com.client as win32
import os

OD = 'C:/DirectoryString/'

# Sub Directory
Dir1 = 'STR - Doc/Mer Reps/'
Dir2 = 'UK & IE ST - ICS/DB/'
Dir3 = 'UK & IE ST - Docs/DB/2024/'
Dir4 = 'UK & IE RDF - Docs/Rep/DB/Aut/'
Dir5 = 'STR - Doc/RMS/'
Dir6 = 'STR - Doc/Int DB/'

directory_1 = OD + Dir1
directory_2 = OD + Dir2
directory_3 = OD + Dir3
directory_4 = OD + Dir4
directory_5 = OD + Dir5
directory_6 = OD + Dir6

def excel_update(directory):
    for filename in os.listdir(directory):
        if filename.endswith('.xlsx') or filename.endswith('.xlsm'):
            print(f"{directory} {filename}")
            file = filename
            xlapp = win32.DispatchEx('Excel.Application')
            xlapp.DisplayAlerts = False
            xlapp.Visible = True
            xlbook = xlapp.Workbooks.Open(directory + file)
            xlbook.RefreshAll()
            xlbook.Save()
            xlbook.Close()
            del xlbook
            xlapp.Quit()
            del xlapp



schedule.every(30).minutes.do(excel_update(directory_2))

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

The initial job runs, but, when it comes to the first repetition, I get the following error.

Traceback (most recent call last):
  File "C:\Users\gat_mbr\OneDrive - PurmoGroup\Projects\pythonProject\MerchantReports\LoopFunction.py", line 45, in <module>
    schedule.every(30).minutes.do(excel_update(directory_2))
  File "C:\Users\gat_mbr\OneDrive - PurmoGroup\Projects\pythonProject\MerchantReports\Lib\site-packages\schedule\__init__.py", line 655, in do
    self.job_func = functools.partial(job_func, *args, **kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: the first argument must be callable

Solution

  • do() accepts a function object and its arguments. Your code calls it with the result of excel_update(directory_2) call, which is not a function, but a good old None.

    Here's how to fix it:

    schedule.every(30).minutes.do(excel_update, directory_2))
    

    See Pass arguments to a job