我希望获得输入的完整命令行。
此:
" ".join(sys.argv[:])
在这里不起作用(删除双引号)。此外,我不想重新加入被解析和拆分的东西。
有什么想法吗?
答案 0 :(得分:26)
你来不及了。当类型命令到达Python时,你的shell已经发挥了它的魔力。例如,引用消耗(正如您所注意到的),变量得到插值等等。
答案 1 :(得分:13)
在Unix环境中,这通常是不可能的...您可以期望的最好的是传递给您的进程的命令行。
因为shell(基本上是任何 shell)可能会在将其输入操作系统执行之前以多种方式处理类型命令行。
答案 2 :(得分:9)
查看the initial stack layout (Linux on i386) that provides access to command line and environment of a program:该过程只能看到单独的参数。
在一般情况下,您无法获得命名行,因为它是键入的。在Unix上,shell将命令行解析为单独的参数,最终调用execv(path, argv)
function that invokes the corresponding syscall。 sys.argv
派生自传递给argv
函数的execve()
参数。您可以使用" ".join(map(pipes.quote, argv))
获得等效的东西但是您不需要例如,如果您想要使用稍微不同的命令行参数重新启动脚本,那么sys.argv
就足够了(in many cases),见Is it possible to set the python -O (optimize) flag within a script?
有一些创意(非实用)解决方案:
在Windows上,本机CreateProcess()
接口是一个字符串,但python.exe仍然以列表形式接收参数。 subprocess.list2cmdline(sys.argv)
可能有助于扭转这一过程。 list2cmdline
专为使用the same
rules as the MS C runtime的应用而设计 - python.exe
就是其中之一。 list2cmdline
不会返回命名行,因为它是键入的,但在这种情况下返回功能等效。
在Python 2上,您可能需要GetCommandLineW()
,以从命令行获取无法在Windows ANSI代码页中表示的Unicode字符(例如cp1252)。
答案 3 :(得分:5)
如上所述,这可能无法完成,至少不可靠。在少数情况下,您可能能够找到shell的历史文件(例如 - “bash”,但不是“tcsh”)并从中获取用户的输入。我不知道你对用户的环境有多少控制权。
答案 4 :(得分:1)
如果您使用的是Linux,我建议使用~/.bash_history
文件或shell history
命令进行修改,但我相信该命令必须在添加到shell历史记录之前完成执行。< / p>
我开始玩:
import popen2
x,y = popen2.popen4("tail ~/.bash_history")
print x.readlines()
但是我发现奇怪的行为,shell似乎并没有完全刷新到.bash_history
文件。
答案 5 :(得分:0)
在Linux上有/proc/<pid>/cmdline
格式为argv[]
(即所有行之间有0x00,你不知道有多少字符串,因为你没有得到argc;虽然你会在文件用完数据时知道它;)。
您可以确定该命令行已经被释放,因为完成了所有转义/变量填充并且参数被很好地打包(参数之间没有额外的空格等)。
答案 6 :(得分:0)
我晚了10.5年,但是...在Linux下,我处理了与OP完全相同的问题(正如其他人所说的,在Windows中,可以从中检索信息)系统)。
首先,请注意,我使用argparse
模块来解析传递的参数。此外,然后假定参数以--parname=2
,--parname="text"
,-p2
或-p"text"
的形式传递。
call = ""
for arg in sys.argv:
if arg[:2] == "--": #case1: longer parameter with value assignment
before = arg[:arg.find("=")+1]
after = arg[arg.find("=")+1:]
parAssignment = True
elif arg[0] == "-": #case2: shorter parameter with value assignment
before = arg[:2]
after = arg[2:]
parAssignment = True
else: #case3: #parameter with no value assignment
parAssignment = False
if parAssignment:
try: #check if assigned value is "numeric"
complex(after) # works for int, long, float and complex
call += arg + " "
except ValueError:
call += before + '"' + after + '" '
else:
call += arg + " "
它可能无法完全涵盖所有极端情况,但对我很有用(它甚至可以检测到像1e-06
这样的数字都不需要引号)。
在上面,为了检查传递给参数的值是否为“数字”,我从this pretty clever answer那里窃取。
答案 7 :(得分:0)
您可以使用提供跨平台解决方案的psutil
:
import psutil
import os
my_process = psutil.Process( os.getpid() )
print( my_process.cmdline() )
如果这不是你想要的,你可以进一步获取父程序的命令行:
my_parent_process = psutil.Process( my_process.ppid() )
print( my_parent_process.cmdline() )
变量仍会被拆分成其组件,但与 sys.argv
不同的是,它们不会被解释器修改。