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()
user2305193
  • 2,079
  • 18
  • 39
  • 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: https://stackoverflow.com/questions/19747371/python-exit-commands-why-so-many-and-when-should-each-be-used – juanpa.arrivillaga Nov 27 '19 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](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – juanpa.arrivillaga Nov 27 '19 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 – user2305193 Nov 27 '19 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". – juanpa.arrivillaga Nov 27 '19 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]`? – user2305193 Nov 27 '19 at 20:59
  • You don't need to define it as anything *it already is just a list*. It may only have one item in it, in which case, you can just append whatever you want. – juanpa.arrivillaga Nov 27 '19 at 21:00
  • thanks everyone, I think the proper way would be to parse the arguments like @QuantumLicht mentions. @ chepner's answer seems most intuitive and readable to me (coming from matlab) which is why I accepted it (and upvoted all other useful answers, especially QuantumLicht's answer) – user2305193 Nov 27 '19 at 22:01

3 Answers3

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.

chepner
  • 497,756
  • 71
  • 530
  • 681
QuantumLicht
  • 2,103
  • 3
  • 23
  • 32
  • 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). – chepner Nov 27 '19 at 21:40
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.

chepner
  • 497,756
  • 71
  • 530
  • 681
-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).

lowtex
  • 707
  • 4
  • 22
  • This is neither an answer to the question nor a valid explanation considering the question was asked for python. – QuantumLicht Nov 27 '19 at 21:35
  • `sys.argv` is an ordinary list *initialized* from the actual argument list of the Python process; this isn't relevant. – chepner Nov 27 '19 at 21:42
  • @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. – lowtex Nov 27 '19 at 21:55
  • @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. – lowtex Nov 27 '19 at 21:57