想要通过 python 的子进程或 pycurl 运行 curl 命令

Want to run a curl command either through python's subprocess or pycurl

我有以下命令将用户添加到 gerrit 实例的管理员组,

 curl -X POST -H "Content-Type:application/json;charset=UTF-8" -u nidhi:pswd http://host_ip:port/a/groups/Administrators/members.add -d '{"members":["user@example.com"]}'

当我在我的终端上 运行 这个命令时,它 运行 完美地给出了预期的输出。

但是,我想在 python 中使用 subprocesspycurl 库执行此命令。

使用subprocess我写了下面的代码,

def add_user_to_administrator(u_name,url):
    bashCommand = 'curl -X POST -H "Content-Type:application/json;charset=UTF-8" -u nidhi:pswd http://'+url+'/a/groups/Administrators/members.add -d '+"'"+'{"members":["$u_n@example.com"]}'+"'"
    bashCommand = string.Template(bashCommand).substitute({'u_n':u_name})
    print bashCommand.split()
    process = subprocess.Popen(bashCommand.split())

没有显示错误,但在管理员组中没有看到任何变化。

我使用 pycurl

进行了相同的尝试
def add_user_to_administrator2(u_name,url):
    pf = json.dumps({"members":[str(str(u_name)+"@example.com")]})
    headers = ['Content-Type:application/json;charset=UTF-8']
    pageContents = StringIO.StringIO()


    p = pycurl.Curl()
    p.setopt(pycurl.FOLLOWLOCATION, 1)
    p.setopt(pycurl.POST, 1)
    p.setopt(pycurl.HTTPHEADER, headers)
    p.setopt(pycurl.POSTFIELDS, pf)
    p.setopt(pycurl.WRITEFUNCTION, pageContents.write)
    p.setopt(pycurl.VERBOSE, True)
    p.setopt(pycurl.DEBUGFUNCTION, test)
    p.setopt(pycurl.USERPWD, "nidhi:pswd")
    pass_url=str("http://"+url+"/a/groups/Administrators/Administrators/members.add").rstrip('\n')
    print pass_url
    p.setopt(pycurl.URL, pass_url)
    p.perform()

    p.close() 
    pageContents.seek(0)
    print pageContents.readlines()

这会引发错误,找不到帐户 members

提到的变量 url 的形式是 host_ip:port。

我已经尝试了很多来修复这些错误。我不知道我哪里错了。任何帮助,将不胜感激。

a) 字符串转义

对于 subprocess/curl 用法,您应该转义字符串标记而不是手动添加额外的 ':

...stuff'+"'"+'more.stuff...

在字符前使用 \ 进行转义,即使用

"curl -X POST -H \"Content-Type:application/json;charset=UTF-8\""

将在 Content-Type 部分保留 "

更多关于转义字符的信息:Lexical Analysis - String Literals

...The backslash () character is used to escape characters that otherwise have a special meaning...

b) popen

正在查看 popen docs their example uses shlex.split() 以将其命令行拆分为参数。 shlex 以不同方式拆分字符串:

print(bashCommand.split())
['curl', '-X', 'POST', '-H', '"Content-Type:application/json;charset=UTF-8"', '-u', 'nidhi:pswd', 'http://TEST_URL/a/groups/Administrators/members.add', '-d', '\'{"members":["TEST_USER@example.com"]}\'']

print(shlex.split(bashCommand))
['curl', '-X', 'POST', '-H', 'Content-Type:application/json;charset=UTF-8', '-u', 'nidhi:pswd', 'http://TEST_URL/a/groups/Administrators/members.add', '-d', '{"members":["TEST_USER@example.com"]}']

您可以看到 shlex 删除了多余的引号。

c) http 响应代码

尝试使用 curl 中的 -I 选项来获取返回的 HTTP 响应代码(以及 HTTP headers 的其余部分):

$curl -h
...
-I, --head          Show document info only

即使您使用 subprocess 来 start/make 请求,它仍应将 return 值打印到控制台(stdout)。

d) 把它们放在一起

我更改了 urlu_name 插入字符串的方式。

import shlex
import subprocess


def add_user_to_administrator(u_name, url):
    bashCommand = "curl -I -X POST -H \"Content-Type:application/json;charset=UTF-8\" -u nidhi:pswd http://%(url)s/a/groups/Administrators/members.add -d '{\"members\":[\"%(u_n)s@example.com\"]}'"
    bashCommand = bashCommand % {'u_n': u_name, 'url': url}
    args = shlex.split(bashCommand)
    process = subprocess.Popen(args)

add_user_to_administrator('TEST_USER', 'TEST_URL')

如果 none 有帮助,并且您没有收到 gerrit 的响应,我会检查 gerrit 日志,看看它收到您的请求时会发生什么。