0

Coming from Matlab (new to python) I'm used to 'cheat' a bit setting varargin manually in some cases... I need to adapt some code and would like to leave lines ASDF=... and BSDF=... unchanged. For this purpose I would want to set sys.argv[1]... can this be done and would this be considered bad practice?

#read ASDF and BSDF from a text file, with the section that is specified by the argument provided
if len(sys.argv) == 1:
    sys.argv[1]='DEFAULT'
    print('Using ' + sys.argv[1]):
    ASDF =   config.get(sys.argv[1],'ASDF');
    BSDF =   config.get(sys.argv[1],'BSDF');

elif len(sys.argv) == 2:
    print('Using ' + sys.argv[1]):
    ASDF =   config.get(sys.argv[1],'ASDF');
    BSDF =   config.get(sys.argv[1],'BSDF');
else:
    print('too many inputs, don''t confuse me...')
    quit()
7
  • you really shouldn't be using quit() outside of an interactive interpreter session, btw. Rarely do you need to explicitely temrinate the program anyway.. but if you do, read this: stackoverflow.com/questions/19747371/… Commented Nov 27, 2019 at 20:54
  • Anyway, have you tried to do anything? It simply returns a list, and you can modify it. As to whether or not it's best practice, I would lean on maybe not, but there is probably some alternative approach that keeps the same spirit, but I would elaborate on your actual problem that you are trying to solve, because this all smells like the X-Y problem Commented Nov 27, 2019 at 20:56
  • @juanpa.arrivillaga I suspect it's an XY problem, that's why I wrote I'm a beginner, please help me by pointing out the flaws in hypothesis building (to form X instead of Y). I tried setting sys.argv[1] but I'm getting IndexError: list assignment index out of range errors Commented Nov 27, 2019 at 20:57
  • OK, so then you need to append to that list. Again, it's just a list. But anyway, what are you actually trying to solve. Because the answer to your question is "yes, yes you can". Commented Nov 27, 2019 at 20:58
  • so there's nothing wrong with setting sys.argv manually? I just need to define it as a list and then set [1]? Commented Nov 27, 2019 at 20:59

3 Answers 3

2

Maybe you should use the default argparse module for argument parsing: https://docs.python.org/3/library/argparse.html

I am not 100% sure I understand what you are trying to do, but here's a tentative solution:

#read ASDF and BSDF from a text file, with the section that is specified by the argument provided

import argparse

parser = argparse.ArgumentParser(description="My argument parser")

parser.add_argument('some_argument')
parser.add_argument('section', nargs='?', default="DEFAULT")

args = parser.parse_args() # Will parse sys.argv by default

section = args.section
print('Using ' + section)
ASDF =   config.get(section,'ASDF');
BSDF =   config.get(section,'BSDF');

Argparse will manage errors when the number of arugments is not correct. The syntax might also be closer to what you know in matlab.

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

1 Comment

I deleted config = {} because the use of config is consistent with a predefined instance of ConfigParser (though the creation of that instance isn't shown in the question).
1

TL;DR Don't use sys.argv; use argparse.


What you are doing now doesn't require setting sys.argv[1]; just use "DEFAULT" where you would have used it.

if len(sys.argv) == 1:
    print('Using DEFAULT'):
    ASDF = config.get('DEFAULT', 'ASDF');
    BSDF = config.get('DEFAULT', 'BSDF');

elif len(sys.argv) == 2:
    print('Using ' + sys.argv[1]):
    ASDF = config.get(sys.argv[1],'ASDF');
    BSDF = config.get(sys.argv[1],'BSDF');
else:
    print('too many inputs, don''t confuse me...')
    sys.exit(1)

Setting sys.argv[1] is useful if you want to factor out the calls to config.get, for example,

if len(sys.argv) == 1:
    # there is no sys.argv[1] to assign to;
    # you need to append to the list.
    sys.argv.append('DEFAULT')
elif len(sys.argv) > 2:
    sys.exit(1)

print('Using ' + sys.argv[1]):
ASDF = config.get(sys.argv[1],'ASDF');
BSDF = config.get(sys.argv[1],'BSDF');

That said, in general, you don't use sys.argv directly. Use argparse as in QuantumLicht's answer.

Comments

-2

While it may be possible to do this by setting setting sys.argv = [...] (maybe, its been a while since I used python), doing this would definitely be considered bad practice.

The variable sys.argv is a holdover from C. In C, the main function of a program looks something like this:

int main(int argc, char *argv[]) {
    ...
}

When the program is loaded, the arguments that were passed to the program are loaded into a continuous block of memory, and it is not safe to assume there is any extra space after the space that has already been allocated for the arguments. Since the value you would like to assign to the arguments might be a string that is longer than the original argument, or may be an argument after the last argument the program was started with, doing something like that could corrupt the memory of your program or trigger some sort of memory access exception (in C).

4 Comments

This is neither an answer to the question nor a valid explanation considering the question was asked for python.
sys.argv is an ordinary list initialized from the actual argument list of the Python process; this isn't relevant.
@QuantumLicht Would my solution not work in python? I think it would, which makes this an answer to the question. Also, a part of the question was about best practices. My C explanation was about why it would not be a best practice, not about how it works in python, which makes it a valid explanation considering the question.
@chepner I believe it is relevant because I was providing an explanation of why it would be a bad practice given the history of the language, which was a part of the question.

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.