Script will only run in Powershell - python

First off I looked in the documentation and found this:
http://www.tutorialspoint.com/python/python_command_line_arguments.htm
And then I also found this:
how to execute a python script file with an argument from inside another python script file
I am using pycharm 2.7.3 and when I try to run my script I get and error (the error is not pycharm related). THe only way around this error I have found out to be is to run the script through the windows PowerShell with a couple of "arguments" (is that what its called?)
The code that follows is what makes up my script, temp.py
from sys import argv
# this what the Ide fails to run
scripts, first, second, third = argv
print "The script is called:", scripts
print "Your first variable is:", first
print "Your second variable is:", second
print "Your third variable is:", third
Next is what I types into the powershell
NOTE: The above code is temp.py
python temp.py first 2nd 3rd
1) What are those pieces of text called that appear after the "python temp.py", is it arguments?
2) Is it possible to run the code with the so called arguments in the IDE (I am using pyCharm)
3) If '2)' = True, how so?

1) What are those pieces of text called that appear after the "python temp.py", is it arguments?
Yes, the things you pass after temp.py on the shell are called "arguments", or "command line arguments". Sometimes they're called "parameters" instead, sometimes with the word "actual" as a prefix.*
And note that temp.py and all of its arguments are themselves arguments of python.
The sys.argv variable that you're using specifically gives you:
The list of command line arguments passed to a Python script…
2) Is it possible to run the code with the so called arguments in the IDE (I am using pyCharm)
Yes. Almost every IDE has a way to do this.
3) If '2)' = True, how so?
Read the PyCharm docs for details, but IIRC, they're part of the "run/debug configuration"; when you use the "Edit Configurations" command and edit one, there's a box labeled "Script Parameters" for you to enter the arguments.
* Using "parameters" is a bit misleading. Speaking technically, using the terminology Python uses for function calling, you should say that your script has a single parameter, a variable-positional parameter which gathers all of the arguments used to call it, which you can access as sys.argv. But as you can guess, nobody actually says things that way. If someone says "command line parameters" or "script parameters", they mean "the things in sys.argv".

Related

How to pass arguments in Spyder using sys argv [duplicate]

This question already has answers here:
How to use argv with Spyder
(4 answers)
Closed last year.
I am struggling with passing 2 arguments in spyder using the command line. I have used the run-->configuration per file and in the command line options put JPEGtoPNG.py/Poxedex/new/. The JPEGtoPNG is the python file and the arguments to be passed are poxedex and new.
Dilemma:
When i run print(sys.argv[0]) it prints:
runcell(0, '/Users/chideraokafor/JPEGtoPNG.py')
which i understand is the default.
However when i run print(sys.argv[1]) it prints:
IndexError: list index out of range.
I have tried everything but still, it's not passing the two arguments, and I really don't want to use pycharm.
If Poxedex and new are command line arguments for a script, JPEGtoPNG.py, execution should be:
python JPEGtoPNG.py Poxedex new
Not / separated.
Note that the error you get is because you are not passing command line arguments and as such sys.argv is a list of length one (that one being the script name) and indexing starts at 0 in Python so accessing the second element via sys.argv[1] is indeed out of range.
Since Spyder provides a Python console and the options you are passing via the menu are intended as that - options and not arguments - you might find it easier to run the script(s) from the command line, for example using VSCode.
Even if you don't want to use VSCode, you can just open a terminal window and invoke the script from there. Just check your environment variables to ensure Python is on your system (or user) path.

Access previous bash command in python

I would like to be able to log the command used to run the current python script within the script itself. For instance this is something I tried:
#test.py
import sys,subprocess
with open('~/.bash_history','r') as f:
for line in f.readlines():
continue
with open('logfile','r') as f:
f.write('the command you ran: %s'%line.strip('\n'))
However the .bash_history does not seem to be ordered in chronological order. What's the best recommended way to achieve the above for easy logging? Thanks.
Update: unfortunately sys.argv doesn't quite solve my problem because I need to use process subtitution as input variables sometimes.
e.g. python test.py <( cat file | head -3)
What you want to do is not universally possible. As devnull says, the history file in bash is not written for every command typed. In some cases it's not written at all (user sets HISTFILESIZE=0, or uses a different shell).
The command as typed is parsed and processed long before your python script is invoked. Your question is therefore not related to python at all. Wether what you want to do is possible or not is entirely up to the invoking shell. bash does not provide what you want.
If your can control the caller's shell, you could try using zsh instead. There, if you setopt INC_APPEND_HISTORY, zsh will append to its history file for each command typed, so you can do the parse history file hack.
One option is to use sys.argv. It will contain a list of arguments you passed to the script.
import sys
print 'Number of arguments:', len(sys.argv), 'arguments.'
print 'Argument List:', str(sys.argv)
Example output:
>python test.py
Number of arguments: 1 arguments.
Argument List: ['test.py']
>python test.py -l ten
Number of arguments: 3 arguments.
Argument List: ['test.py', '-l', 'ten']
As you can see, the sys.argv variable contains the name of the script and then each individual parameter passed. It does miss the python portion of the command, though.

When using os.execlp, why `python` needs `python` as argv[0]

The code is like this:
os.execlp('python', 'python', 'child.py', #other args#) # this works
os.execlp('python', 'child.py', #other args#) # this doesn't work
I read this question: execlp() in python
But I'm still confused. The answer said:
The first argument is the program to execute (found on the PATH). The
rest are the sys.argv arguments to the program.
However, if I run: python child.py 1 2 3 and the sys.argv of this process would be ["child.py", "1", "2", "3"], where the python doesn't exist. Then why should I add python as the second parameter of os.execlp?
When python is executed, it creates sys.argv for you. The values in that list are based on the arguments passed to it by the operating system, but it leaves off the sys.executable value from that list.
In other words, when Python is invoked, it sets sys.argv to everything but it's own executable.
When you invoke a new executable via os.execlp(), you still need to include Python in that as that is what executable that the OS will run. The first two values of what you a pass to os.execlp() are still required, whatever you find in sys.argv later on.
The second python is a name for python, it can be any string, but it has to be there.
See the second paragraph of http://docs.python.org/3/library/os.html?highlight=os.exec#process-management:
The various exec* functions take a list of arguments for the new program loaded into the process. In each case, the first of these arguments is passed to the new program as its own name rather than as an argument a user may have typed on a command line. For the C programmer, this is the argv[0] passed to a program’s main(). For example, os.execv('/bin/echo', ['foo', 'bar']) will only print bar on standard output; foo will seem to be ignored.
I realize this was answered LONG ago and the answer is basically right, but there are a few things that are misleading in the way it is worded and in the comments to the answer that I would like to address.
First, I think the clearer way to state what is happening is to highlight that the difference is between the Unix argv list that a process gets handed by the OS and the python sys.argv. The python sys.argv is the Unix argv list with the first element (the command name) removed.
The various os.exec* commands use their first argument to be the actual executable to invoke and the remainder of the line is the Unix argv list, which means that the second argument passed to execlp will be interpreted by the executable as the command line name it was invoked as.
Which takes us to the problem with the comment. The reason that the ls example os.execlp('ls','.') "works" is not because ls does anything special to detect it is called with too few arguments. This example code starts the 'ls' executable with the unix argv list being ['.']. That just means that the ls executable gets started while being told (oddly) that it was invoked as '.', and there are no other command line arguments. And what does ls do when it is run with no other command line arguments: it prints the contents of the current directory, or exactly what one mistakenly thought they were doing when the invoked os.execlp('ls', '.').
You can see that this example really isn't "working" by instead trying os.execlp('ls', '/some/non-existant/path'). That also prints out the contents of the current working directory, and would not be mistaken for "working".

execlp() in python

I was reading programming python 4th edition by Mark Luze, Oreilly, by teaching myself.
There's an example on how to fork a child process, which I do not quite understand:
os.execlp('python', 'python', 'child.py', #other args#)
In an interactive shell(like bash), I know I can type python child.py #args# to ask python interpreter to run child.py with args.
Why are there TWO 'python' in the execlp() function? If I put only one python in the function, I would get an error complainting cannot find file or directory, which is the 1st args of child.py
The first argument is the program to execute (found on the PATH). The rest are the sys.argv arguments to the program.
The first such argument is the program name used to invoke it, and the display value used in the OS process list. It is the value of sys.argv[0] in a python script.
First of all, execlp is rarely used today. In most cases, you'd use the subprocess module, like this:
subprocess.call(['python', 'child.py'])
The first argument of execlp is the file you want to execute.
The latter arguments form the argument array to that program (sys.argv in Python). The first argument is then the name the program got invoked with. For example, Python sets the name to '-c' if the program is being run with the -c option. Similarly, grep behaves differently depending on the first argument, so that users can execute rgrep to imply grep -r.

When running python files in terminal, do return commands not get executed?

I am trying to understand how running a python file in terminal vs running it via IDLE, for instance, may change the way the code is interpreted. I didn't think there would be any difference, but I've been noticing that any "Return" commands in the code get ignored when the code is run on the mac terminal. Why is this the case?
For example, take a code as simple as the following:
def talk(arg):
return arg
talk("Hello!")
Now if I run this in terminal, I would expect it to print out "Hello!", because it would run the function talk on the given arg "Hello!" and return it. I do get the desired result if I change the last line to print talk("Hello!") then it works.
The commands do get executed, but unlike in the REPL, return values in a script are not automatically printed. You will need to use print/print() in order to actually get any output.

Categories

Resources