I wrote a program to gradually lower the volume of my computer when I go to sleep so I can fall asleep with TV or music on. This was my first time using argparse and I feel like there should be a cleaner way to deal with default values of optional arguments. Any other feedback of course also welcomed.

import vol
from time import sleep
from subprocess import call, check_output
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-d", "--delay", help="time (in minutes) until volume begins to lower", type=int)
parser.add_argument("-m", "--minutes_until_mute", help="time (in minutes) to set the volume to mute", type=int)
a = parser.parse_args()
minutes_until_mute = a.minutes_until_mute if a.minutes_until_mute else 30
delay = a.delay if a.delay else 0
current_volume = check_output(['osascript', '-e', 'set ovol to output volume of (get volume settings)'])

for i in range(minutes_until_mute):
    percent_of_volume = (-1.0/(minutes_until_mute**2))*(i**2) + 1 #quadratic function with maximum at (0, 100%) and crossing at (minutes_until_mute, 0)
    new_volume = int(float(current_volume) * percent_of_volume)
    call(["vol", "out", str(new_volume)])
    call(["vol", "info"])

call(["vol", "mute"]) #rounding errors mean we don't get exactly to 0
  • \$\begingroup\$ As you ask for any other comments, I will say: think to the planet and shutdown your computer at the end of the delay ! (this question caught my eye because I love to go to sleep with music and I used for years a python script to turn off my computer after a specified time or another to turn it off once my vlc playlist is completed) Well maybe it's not a computer that you shutdown anyway :) \$\endgroup\$
    – mgc
    Commented Feb 7, 2016 at 20:03

2 Answers 2


"I feel like there should be a cleaner way to deal with default values of optional arguments"

Yes, there is. Per the documentation of ArgParse, you can specify a keyword argument default and give it the value you want.

parser.add_argument("-d", "--delay", help="Delay in minutes until starting mute", type=int, default=0)

Documentation here
Tutorial here

  • \$\begingroup\$ Duh. I must've looked right at that a bunch of times. \$\endgroup\$ Commented Feb 5, 2016 at 12:14


You could convert current_volume to its relevant and usable type (float) at you get it instead of reconverting it everytime you use it.

current_volume = float(check_output(['osascript', '-e', 'set ovol to output volume of (get volume settings)']))
new_volume = int(current_volume * percent_of_volume)

Off-by-one error

This may or may not be an error depending on what you had in mind.

You've defined a function which is supposed to return 100% initially and 0% at the end.

Your function reaches 0 when (-1.0/(minutes_until_mute**2))*(i**2) + 1 which is when i == minutes_until_mute. Unfortunately, this is not the last value of your loop : the last value of range(n) is n-1.

  • \$\begingroup\$ Eh. Technically an error, although not one that really affects anything. For best practices, though, best to just do range(minutes+1)? \$\endgroup\$ Commented Feb 5, 2016 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.