0

I want the command that was used to invoke the python script to be available in the script itself.

Like:

python3 foo.py -a -b
python foo.py -c

Is it possible in foo.py to get these whole commands.

manly1
  • 3
  • 1
  • Use the `argparse` module. [Link](https://docs.python.org/3/library/argparse.html) – sudo97 Jan 27 '20 at 08:21
  • Possibly a duplicate of https://stackoverflow.com/questions/4033723/how-do-i-access-command-line-arguments-in-python – Laurent H. Jan 27 '20 at 08:22
  • Argparse will give me the arguments passed but not the python version/option like python or python3. I can use sys.version_info for getting version and assume python3 when it is not < 3 but that won't work on machine with python version 3 as default. there python will be the appropriate command. – manly1 Jan 27 '20 at 08:26

3 Answers3

2

Use sys.executable and sys.argv:

from __future__ import print_function
import sys
print(sys.executable)
print(sys.argv)

The above should work with Python 2 and Python 3 (below is from macOS):

howes% python2 blah.py 1 -m 123 53131
/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
['blah.py', '1', '-m', '123', '53131']
howes% python3 blah.py 1 -m 123 53131
/usr/local/opt/python/bin/python3.7
['blah.py', '1', '-m', '123', '53131']

EDIT

If that is not enough, you can try the psutil library (pip install psutil):

from __future__ import print_function
import os, psutil
us = psutil.Process(os.getpid())
print(us.cmdline())
print(us.exe())

macOS 10.15.2 (Python 2.7 and Python 3.7*):

howes% python blah.py -a 1 -b 2 3 4
['/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python', 'blah.py', '-a', '1', '-b', '2', '3', '4']
/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
howes% python3 blah.py -a 1 -b 2 3 4
['/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python', 'blah.py', '-a', '1', '-b', '2', '3', '4']
/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python
howes% 

Windows 10 (Python 2.7 and Python 3.8):

C:\Users\b.howes>python2 blah.py -a 1 -b 2 3 4
['python2', 'blah.py', '-a', '1', '-b', '2', '3', '4']
C:\Python27\python2.exe

C:\Users\b.howes>python blah.py -a 1 -b 2 3 4
['python', 'blah.py', '-a', '1', '-b', '2', '3', '4']
C:\Users\b.howes\AppData\Local\Programs\Python\Python38\python.exe

Brad Howes
  • 114
  • 1
  • 6
  • sys.executable will surely give the path of the python used and one can maybe extract python2 or python3 from it but this won't work on all machines. Like on windows I'll get python.exe or something different on another os. I simply want what the user used in command. (python/python2/python3). One approach I can think of is getting sys.version_info[0] and then doing python --version in subprocess and then compare these two to know what user used. Is there a simpler way to do this? – manly1 Jan 27 '20 at 09:30
  • I updated my answer with a pointer to `psutil` which may help. – Brad Howes Jan 27 '20 at 10:56
  • psutil.Process().cmdline() solves the issue. Thank you. – manly1 Jan 28 '20 at 05:15
1

The closest thing I can think of is this:

import sys
import os

s = ""
for arg in sys.argv:
    s = s + arg + " "

print(os.path.basename(sys.executable) + " " + s)

Example output (on windows):

$ python tmp.py -a -b
python.exe tmp.py -a -b
user1308345
  • 1,032
  • 1
  • 8
  • 14
0

In Unix environments, you do not have access to the command line itself -- this is not python specific. However, a shell or other well-behaved program executing another program will place the executable name or path in the first argument.

Python's sys.argv is not giving you, however, the OS-level command line.

You can obtain the python executable with sys.executable, but neither this nor sys.argv would give you the full command line:

Say this is foo.py:

import sys

print(sys.argv)
print(sys.executable)

Then:

$ python -O foo.py a b c
['foo.py', 'a', 'b', 'c']
/usr/bin/python

As you can see, the -O flag is not present there.

If you really need these, the way to obtain it is probably dependent on the OS (I do not know if python gives you access to these "low-level" command line arguments).

If you are on Linux, you could do:

import os

with open("/proc/%s/cmdline" % os.getpid(), "rb") as f:
    cmdline = f.read()

print(cmdline.split(b"\x00"))

With the result:

$ python -O foo.py a b c
['python', '-O', 'foo.py', 'a', 'b', 'c', '']

Note the last empty string is due to how cmdline has NUL-terminated strings, so the last character will be b"\x00", hence split() will give you the last empty string.

petre
  • 1,485
  • 14
  • 24