Batch file not running python script in task scheduler

Question:

I have a scraping python script and a batch file that when run from CMD works perfectly however when I try to run it from Task Scheduler nothing happens.

I know there are a lot of questions regarding the same issue but I have tried all of the proposed answers and non of them seem to work.

Don’t know if this is relevant but script would open Firefox and scrape some websites.

Have tried adding full permissions to the folders and files that I am using.
Also, have tried in Task Scheduler to set up "Run wheter user is logged on or not", "Run with highest privileges" , "Start in (optional): add/bactch/file/path" and so on

Batch file:

py "C:python_testmyscript.py"

It should run the python script which opens Firefox and scrapes some websites, gets their links and saves them in a csv file

Here is myscript.py:

import datetime
import time
import csv
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import os

file_path = r"C:General{0:%Y%m%d}results{0:%Y%m%d%H%M%S}.csv".format(datetime.datetime.now())
directory = os.path.dirname(file_path)

try:
    os.stat(directory)
except:
    os.mkdir(directory)

from bs4 import BeautifulSoup
 
 
def init_driver():
    caps = DesiredCapabilities.FIREFOX
    caps['marionette'] = True
    driver = webdriver.Firefox(capabilities=caps)
    driver.wait = WebDriverWait(driver, 15)
    return driver
 

xpath = {
    'english': '//*[@id="xxx"]',
    'soort': '//*[@id="xxx"]/option[text()='|- Announcement of change in denominator or in thresholds']',
    'start': '//*[@id="xxx"]',
    'end': '//*[@id="xxx"]',
    'submit': '//*[@id="xxx"]',
    'pub_sort': '//*[@id="xxx"]',
}
 
if __name__ == "__main__":

    driver = init_driver()
    try:
        driver.get("http://SOMEWEBSITE") 
        driver.find_element_by_css_selector('[id$=hplEnglish]').click()
    except Exception:
        DoNothing = ""

    
    time.sleep(2)
    driver.find_element_by_css_selector('[id$=hplEnglish]').click()
    time.sleep(3)
    #alert_obj = driver.switch_to.alert
    #alert_obj.dismiss()
    #driver.find_element_by_xpath(xpath['english']).click()
    today = datetime.datetime.now()
    driver.wait.until(EC.element_to_be_clickable((By.XPATH, xpath['soort']))).click()
    driver.find_element_by_xpath(xpath['start']).send_keys((today-datetime.timedelta(weeks=1)).strftime('%d/%m/%Y'))
    driver.find_element_by_xpath(xpath['end']).send_keys(today.strftime('%d/%m/%Y'))
    driver.find_element_by_xpath(xpath['submit']).click()
    for i in range(2):
        driver.wait.until(EC.element_to_be_clickable((By.XPATH, xpath['pub_sort']))).click()
    time.sleep(5)
    html = driver.page_source
    driver.quit()
    
    results = BeautifulSoup(html, 'html.parser').find('div', { 'id': 'SearchResults'}).table
    res = [['issuer', 'type', 'date']]
    for x in results.find_all('tr')[1:]:
        # print(x.text.strip())
        try:
            a, b, c = [i.text.strip() for i in x.find_all('td', class_='resultItemTop')[:3]]
            res.append([a,b,c])
        except ValueError:
            continue

        
    with open(file_path, 'w', newline='') as result:
        writer = csv.writer(result, delimiter=',')
        writer.writerows(res)
        print('finished')

Asked By: davork

||

Answers:

Introduction

I suggest to read first What must be taken into account on executing a batch file as scheduled task?

Issue 1: Current directory

The first issue here is most likely the current directory on running the batch file.

Windows sets the directory of the batch file as current directory on double clicking a batch file, except the batch file path is a UNC path starting with \computernameshare.

The current directory for a scheduled task is by default %SystemRoot%System32, i.e. the Windows system directory which of course is special protected against modifications. Many batch files expect that the current directory is the directory of the batch file and not any other directory.

Solution 1: Define Start in directory in properties of scheduled task.

  • Start Windows Task Scheduler.
  • Navigate to the task and double click on it to open the Properties of the task.
  • Select tab Action and click on button Edit.
  • There is Start in (optional). Enter here the path of the executed batch file.
  • Click two times on button OK to save this important modification in properties.

Solution 2: Make batch file directory the current directory using CD.

In the batch file insert after first line being usually @echo off the line:

cd /D "%~dp0"

This command line changes the current directory from default %SystemRoot%System32 to the directory of the batch file as long as the batch file is not started using a UNC path.

Open a command prompt window and run cd /? for help on command CD and option /D.

Solution 3: Make batch file directory the current directory using PUSHD.

This solution is best if the batch file is stored on a network resource accessed using UNC path and of course the scheduled task is configured to run with credentials (user account and password) with permissions to read content of the batch file on the network resource.

In the batch file insert after first line being usually @echo off the lines:

setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0"

The batch file should additionally contain as last two line executed before exiting batch file processing the two lines:

popd
endlocal

Open a command prompt window and run pushd /?, popd /?, setlocal /? and endlocal /? for help on these four commands and read also this answer for even more details on these four commands.

Solution 4: Code everything to be independent on current directory.

The fourth solution is writing batch file and Python script for being independent on which directory is the current directory on execution of batch file and Python script.

This solution requires that all files and directories are specified with full qualified file/folder name which means full path + file/folder name + file extension.

The full file/folder paths can be derived from known paths on execution like path of the batch file which can be referenced with %~dp0 inside the batch file and which expands to a path string always ending with backslash which means it can be concatenated with file/folder names without usage of an additional backslash.

See also Wikipedia article about Windows Environment Variables.

Issue 2: Environment variables

Scheduled tasks are often executed with built-in local system account. So all environment variables defined just for the user account used on developing and testing the batch file either are not defined at all or are defined different.

Open from Windows Control Panel from item System the Advanced system settings or press key combination Win+Break if keyboard has a key Break (often as alternate function requiring pressing additionally the key Fn) and clicking next on Advanced system settings on left side. The System Properties dialog is opened wit tab Advanced selected containing at bottom the button Environment Variables… which must be clicked to open the Environment Variables window.

There are two lists of environment variables: User variables for … and System variables. The system variables are defined for all accounts including built-in local system account. The user variables are defined only for the displayed user.

The user variables defined for current user are important and could be a reason why a batch file executed with a double click by current user works, but does not work on being executed as scheduled task with built-in system account. A user PATH is often a main source of not working batch file on execution as scheduled task if the used scripts and executables depend on specific folder paths in local PATH defined in user PATH.

Please take a look on What is the reason for “X is not recognized as an internal or external command, operable program or batch file”? for more information about system, user and local PATH and environment variable PATHEXT used on writing in a batch file just py instead of the script/executable file with full qualified file name.

So it is definitely better to use

"C:Python27python.exe" "C:python_testmyscript.py"

instead of using

py "C:python_testmyscript.py"

which results in cmd.exe searching around for a file py using local PATHEXT and local PATH environment variables which can file if the folder containing file py is defined in user PATH.

I have not installed Python and so don’t know what py really is. It could be a batch file with file name py.cmd or py.bat in which case the command CALL must be used if the batch file contains additional command lines after the command line with py and which perhaps depends on user environment variables. It could be a symbolic link to python.exe in installation folder of Python. I don’t know.

Issue 3: Network resources

Many scheduled tasks access files, folders or data via a network. In this case the scheduled task must be configured to run with the credentials (user account and password) which has the required permissions to access the files, folders or data on the network resource. The usage of the built-in local system account is in this case nearly never the right choice to run the scheduled task because of local system account has usually no permissions to read/write data on any network resource.

Conclusion

It is good practice in my opinion to write a batch file being executed as scheduled task to be as independent as possible on other batch files and environment variables not defined in the batch file executed by Windows task scheduler itself. A design with dependencies on other script files and variables defined outside main script cause often sooner or later (sometimes years later) unexpected execution problems.

The programmer of a script written for execution as scheduled task should really know very well on which files, libraries, environment variables and registry keys/values the script and called executables depend on to work properly.

A batch file containing only one line to execute one application with some parameters is completely unnecessary and just a potential source of not working scheduled task because of the executable to run and its parameters can be in this case also directly set in properties of the scheduled task. There is absolutely no need to run %SystemRoot%System32cmd.exe with implicit option /C to process a specified batch file containing only one command line to execute an application with zero or more parameters because of Windows task scheduler can directly run the application with its parameters, too.

Answered By: Mofi