【发布时间】:2019-03-24 21:05:45
【问题描述】:
我在一个具有 Jython2.5 的系统中工作,但我需要能够调用一些 Google 的 api,所以我编写了一个离线脚本,我想从我的 Jython 环境中调用它并返回给我一些小数据.例如 JobID 或工作表 URL 或来自 Google 的内容。
我尝试了很多方法,但总是从 Windows 收到错误消息,说它找不到指定的文件。
路径以两种方式完成。
第一种使用字符串的方式
stringPath = r"C:\GooglePipes\Scripts\filetobq.py C:\GooglePipes\Keys\DEV-BigQueryKey.json nofile C:\GooglePipes\BQ_Downtime\TESTFILE.CSV dataset1 table1"
第二种方式,作为一个序列(根据文档,使用shell=false 提供一个序列)
seqPath = [r"C:\GooglePipes\Scripts\filetobq.py",r"C:\GooglePipes\Keys\DEV-BigQueryKey.json","nofile",r"C:\GooglePipes\BQ_Downtime\TESTFILE.CSV","dataset1","table1"]
调用
data, err = Popen(seqPath, shell=True, stderr=PIPE, stdout=PIPE).communicate()
#Read values back in
print data
print err
将seqPath 替换为stringPath 以尝试任何一种方式。
我整个周末都在做这个,每次我运行它都会从 Windows 得到
The system cannot find the path specified.
来自err 打印。我一直无法调试比这更进一步。我不太确定发生了什么。当我将stringPath 变量直接粘贴到计算机的命令窗口中时,它会执行。
我还打电话给subprocess.list2cmdline(seqPath) 看看它在输出什么。它给我一个?在字符串前面,但我无法弄清楚这意味着什么。我可以将字符串的其余部分粘贴到命令窗口中,从问号之后开始并执行。
?C:\GooglePipes\Scripts\filetobq.py C:\GooglePipes...
我在 shell 上尝试了许多不同的真假组合,将不同的参数传递给Popen,双斜杠,我从堆栈溢出和其他帮助论坛打开了不少于 30 个选项卡。我现在不知道该怎么做,感谢任何帮助。
编辑
那个?当我进行一些额外的日志记录时,刺痛开始时实际上是一个 NULL 字符。这似乎是我问题的根源。我不知道它为什么会出现,但它出现在我的复制粘贴中。我开始手动输入,我得到了它的工作。当我使用 Jython 程序输入路径时,它又出现了。
【问题讨论】:
-
shell=False对于具有多个参数的单个字符串是完全错误的(在 UNIX 上;Windows 有自己的规则)——shell 是将字符串拆分为 argv 元素列表的工作传递给操作系统execv-family 系统调用。 -
类似地,在 UNIX 上,您不得在传递多元素列表时使用
shell=True,除非该列表的第一个元素是shell 脚本和其余元素是该脚本的参数。但这只是一个信息,因为这不是您手头的实际平台。 -
@CharlesDuffy:为什么它是一个 shell 脚本很重要(只要它有一个 shebang)?
-
@DavisHerring,在 UNIX 上使用
subprocess.Popen([arg1, arg2, ...], shell=True),arg1不应该是 shell 脚本的名称,而是 实际的内联文本 shell 脚本本身。它扩展为['sh', '-c', arg1, arg2, ...],并且sh要求紧跟-c的参数是要执行的脚本文本。 (在该执行的上下文中,arg2 变为$0,其后的参数变为$1,等等)。 -
@DavisHerring, ...如果您不遵守该规则,您的进一步论点将简单地消失而不会受到尊重:考虑
subprocess.Popen(['ls', '/tmp'], shell=True);/tmp在$0中传递,但 shell 脚本ls不检查$0,因此运行的程序ls永远不会传递/tmp参数。
标签: python subprocess jython-2.5