0

I'm pretty much a complete newbie when it comes to Python, and googling this leads to a lot of information about parameters... but not this specific question.

But here's the question: Is there an easy way to make a Python script require a variable when called from outside the script (e.g. Bash)? I realize I can just test on sys.argv, but it really seems like a clunky solution.

For example, could I construct this script so sys.argv[1] has to be passed to use the script without doing tests on it here?:

#!/usr/bin/env python
import string
import random
import sys

def RandomString(length=6):
    x=''.join(random.choice(string.ascii_uppercase) for i in range(length))
    return x

random.seed(sys.argv[1])
y=RandomString()
print y
9
  • You do realize that your question is "Can I write a script that requires a certain variable to exist without writing any code that actually ensures that the variable exists?" right? Commented Sep 17, 2014 at 23:15
  • If I understand what you're saying, you want the requirement to somehow be checked before your script is run. This is therefore not a Python question, but a shell question. Commented Sep 17, 2014 at 23:16
  • How would arguments be nonoptional other than by the code erroring when the argument is missing? Commented Sep 17, 2014 at 23:16
  • 1
    possible duplicate of What's the best way to grab/parse command line arguments passed to a Python script? See also Argument parsing in Python: required vs. optional Commented Sep 17, 2014 at 23:25
  • 1
    How does your script run if you don't give it that argument? It raises an error, right? Isn't that what any 'requirement' would do - raise an error if you don't give it the right arguments? So the real question is: what kind of error message do you want?. Commented Sep 18, 2014 at 0:09

4 Answers 4

2

Use the argparse module. You can define positional arguments that are required, and it will return an error if that argument is not included.

parser = argparse.ArgumentParser()
parser.add_argument('RandomSeed')
args = parser.parse_args()

random.seed(args.RandomSeed)

Usage of the above to lines from bash would be something like:

python main.py thisisarandomstring

Argparse is a nice way to parse your arguments for a command line application(and is a preferred, or good avenue to take when you make a command line app). It automatically generates you some help pages and other documentation, and generates appropriate errors without you having to do all the overehead yourself.

Check out this link for a pretty nice tutorial.

Sign up to request clarification or add additional context in comments.

5 Comments

@user2875994 tried to make it a little more clear if this is all new
@user2875994: beware, if the argument looks like an option (starts with - then argparse won't recognize it as randomseed argument)
You could call the script with python main.py -- -randomstring, although I won't argue that's an ideal solution.
@chepner can you hop on the python chat? I don't understand the edit you made, perhaps you can teach me? I don't see anything about RandomSeed on the docs
Where in the code does it connect the argument "RandomSeed" to argv[1]? Is it add_argument()? If so, if I add multiple arguments, will the first one I add be argv[1], second one argv[2], etc.? Also, this might be a stupid question, but what does it mean to parse an argument? Thanks.
1
  • Argparser is not safe. "Argparse has built-in magic behavior to guess if something is an argument or an option." "Argparse currently does not support disabling of interspearsed arguments." Ref: http://click.pocoo.org/3/why/
  • You should always check argv because that is what is going to be used in your later code. Avoiding it seems nonsensical.

An answer without running "tests" on argv the best I know how to. At least here we are not looking at argv[1]:


#!/usr/bin/env python
import sys

if len(sys.argv) == 1:
    print 'not read in...exiting'
    exit()
print 'read in no problem'

2 Comments

I'm not entirely sure what is magical about "does the argument start with - (or a character in the parser's prefix_chars keyword argument)?".
@chepner: if OP wants to accept any first command-line parameter as a random seed then argparse's behaviour to recognize options won't be helpful here.
0

Here's one possible solution with argparse, that will allow any string as a first argument. It's got two serious problems though: you can't define any optional arguments, which leads to the need to disable the -h/--help option. The technique for disabling options is a bit of a hack. Looking at the source, it's not enough to set prefix_chars to an empty string, but a tuple whose first element is an empty string. or maybe just an empty sequence. There might be some other issues as well.

from argparse import ArgumentParser
p = ArgumentParser(add_help=False, prefix_chars=("",))
p.add_argument("randomseed")

args = p.parse_args()

random.seed(args.randomseed)

Then a call like

python main.py -foo

would set args.randomseed to the string -foo.

Given all this, I think you will just have to accept you'll have to verify in-script that sys.argv has at least one command-line argument, since there is no better way to have bash check for you.

try:
    randomseed = sys.argv[1]
except IndexError:
    # Do something here; I suggest just using a value that 
    # lets random.seed() invoke its default, no-argument behavior
    randomseed = None

Comments

-1

This an extremely rich resource you should read about this: https://stackoverflow.com/a/4118133/3767980

For below, I am just checking to see if the string has anything in it. If it is empty (not read in) it will print to the terminal and exit.

#!/usr/bin/env python
import string
import random
import sys

# testing argv[1]

if 'argv[1]' in locals():
    print 'read in, no problem'
else:
    print 'not read in...exiting'
    exit()
fi

References:

5 Comments

Unless I misunderstood your post, this seems to be exactly what I asked if you could avoid - running tests on the argv. I'm looking into KDEx's posted answer at the moment.
Sorry, I misunderstood what you meant. See below.
The string argv[1] is not going to appear as a key in the dictionary returned by locals().
Not even argv is going to be in locals() unless you change the import statement to from sys import argv, but the existence (or not) of argv only demonstrates that you've imported it, which is not very useful in this context.
I realized this was not the best solution so I submitted a new answer. But I figured it was still useful to leave this up. But yes, I agree with you.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.