22
votes

I'm trying to set up a recurring Python task through windows task scheduler.

I have had success when I input the path to 'python.exe' and provide the script's path as a parameter to windows task scheduler (see screenshot below)

windows task scheduler

However, I want to be able to choose a particular virtual environment in which to run the script. I don't have much knowledge of venv, and I typically use it by opening cmd and running Scripts\activate.bat in the desired virtual environment directory.

How can I accomplish 'run task x in venvxxx every 24 hours' using windows task scheduler?

5

5 Answers

23
votes

Create batch file with these commands:

c:\__full_path_to_virtualenv__\Scripts\activate.bat && python __full_path_to_python_script__.py

&& means run command2 if command1 completed successfully.

Then set that batch file as script to run. You don't need to set any additional arguments in task scheduler (or you can set them in batch file anyway) and can set Start in if script has to read/write from specific directory and uses relative paths.

7
votes

This is more verbose but very easy to understand, and - I found the most important - much easier than using Windows Task Scheduler settings when you have lots of scripts. To create another you just copy the .bat file and change one line.

Save this as a .bat file and point to it under Actions > Start a Program > Program/Script:, with no arguments or "Start in" necessary.

set original_dir=%CD%
set venv_root_dir="C:\Python-Venvs\env-name"
cd %venv_root_dir%
call %venv_root_dir%\Scripts\activate.bat

python your_script.py <arg1> <arg2>

call %venv_root_dir%\Scripts\deactivate.bat
cd %original_dir%
exit /B 1

For an installed command-line program, you can replace python your_script.py <arg1> <arg2> ... with <program name> <arg1> <arg2> ....

In addition it's simple to add another script on the following line, rather than attempting to parse sequential scripts into a one-liner for Task Scheduler.

5
votes

Though the answer by mx0 above seems to work, I have set up Task Scheduler to run a flask web app on bootup. In this case, manual starting works fine, but manual ending does not. Ending the task kills the cmd.exe task that sets up the virtual environment, but the python.exe continues to run.

The solution that I found worked was from this reddit post which skips the virtual environment activation to call the python executable directly:

path\to\venv\Scripts\python.exe path\to\script.py

I'm not sure how robust this will be, but at least this way ending the task will end the python.exe

1
votes

I tried with mx0's answer and it works fine as long as your script does not take too long to finish.

I use a different approach in the task scheduler instead using batch files:

In "Program/script" textbox you set the path to Python executable (in my case is inside the virtualenv folder).

"Add arguments" => Just the name of your Python script (name.ppy).

"Start in" => The full path of your Python script (without the name.py).

This way the script runs and wait until the end.

enter image description here

1
votes

My solution is almost identical to mx0, but I've added an extra step to ensure environment parameters each time. Edit the path/to/app for the app_path variable.

It may be a little redundant to check the environment setup every time, but I like ensuring my environment is set.

Simply schedule the execute_app.bat file or run in the cmd prompt. Deactivate command is not needed unless running from an Anaconda prompt. If you use a full path for path/to/app this file can be executed from any directory. I also have a Linux solution using execute_app.sh file below from a terminal.

This answer has been edited to simplify, and to use variables to make this easier to adapt to new projects.

App structure:
app/bin/app.py
app/bin/execute_app.bat
app/env/requirements.txt

# execute_app.bat file
# windows solution

SETLOCAL
set app_path=path/to/app
set env_path=%app_path%/env
set activ=%env_path%/Scripts/activate.bat
set req=%env_path%/requirements.txt
set app=%app_path%/bin/app.py

py -m venv %env_path% && %activ% && python -m pip install --upgrade pip && pip install -r %req% && python %app%
ENDLOCAL
#!/bin/bash

# execute_app.sh file
# Linux solution

app_path='path/to/app'
env_path=$app_path'/env'
activ=$env_path'/bin/activate'
req=$env_path'/requirements.txt'
app=$app_path'/bin/app.py'

python3 -m venv $env_path &&
. $activ &&
python3 -m pip install --upgrade pip &&
pip install -r $req &&
python $app &&
deactivate