Evan Rosica
Evan Rosica

Reputation: 1242

How to tell if a script is run by double-clicking .py file?

I'm working on a Python 3X program which requires at least one command line argument.

Currently, I'm handling arguments using the argparse library, which handles insufficient arguments by displaying a help text, and killing the program. This works great when the program is run from the command line.

However, if the user clicks on the .py or .pyc file itself, there is no opportunity for the user to read the help text, or enter arguments - the program runs and finishes almost instantly. I'd like to find out when my program is run by double-clicking a file so I can run an interactive UI in that case.

In other words, I'd like to have the arguments fed in interactively if the program is clicked on, but to keep the standard behavior of argparse if the program is run on the command line i.e., have the user specify them all at once e.g. python myprogram.py argument1.

In order to do this, I need to know if the program was run from the command line or by double-clicking a file. I know that python does have a facility somewhat like this for checking if a module is imported or run as a script if __name__ == "__main__":.

Minimal Example:

#test.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("inputpath", help="path to plaintext input file")
args = parser.parse_args()
print(args.inputpath)

Running on the command line gives us nice error handling if a user doesn't enter appropriate arguments:

user@MyPC:path/to/file$ python test.py
usage: test.py [-h] inputpathtest.py: error: the following arguments are 
required: inputpath

However, trying to doubleclick on the file just runs it and exits immediately. There is no time to enter arguments or read the error message.


Possible solutions:

One way to do this would be an optional "interactive" argument, which if not present, would prompt the user manually. Defaulting to interactivity on would allow the user to enter inputs if the script was run by doubleclick. However, it would still allow the command line user to use the interactivity option to turn this behavior off. The downside is that the user must enter an option to get "normal" behavior (i.e. interactivity turned off).

Another way I'm investigating is that when run by doubleclick, it appears sys.argv = ["pathtofile", '', '', '', '', '', '', '', '']. This should be a unique way to tell if the script is run by doubleclick or from a terminal.

This works at least for me on Windows 10:

if sys.argv[1:]==['']*8:
    print("Running from a doubleclick")
else:
    print("running from a terminal")

So just insert your commandline and interactive UIs instead of print statements and voila.

I'm keeping this open in case anyone has a more elegant answer.

Upvotes: 2

Views: 985

Answers (1)

MoxieBall
MoxieBall

Reputation: 1916

You can use the length of sys.argv to get as many arguments as you want after the ones provided from the command line:

import sys
desired_args = 4  # number of arguments you want
arguments = sys.argv[1:] . # [1:] because the first one is your script
for i in range(desired_args-len(arguments)):
    arguments.append(input("Enter another argument: "))

Or, if you want to let the user input arguments until they enter a blank line, replace the for loop with:

while True:
    arg = input("Enter another argument")
    if arg == '':
        break
    else:
        arguments.append(arg)

Upvotes: 1

Related Questions