如果 运行 从 Python 处理,则 getaddrinfow 失败

getaddrinfow fails if running process from Python

我尝试从我的 python 脚本 运行 第 3 方进程 (nsqd.exe) 但是当我这样做时 nsqd 无法绑定套接字。我不知道为什么。

我正在使用的脚本:

import subprocess
import sys

proc = subprocess.Popen(['nsqd.exe', '-tcp-address="127.0.0.1:{}"'.format(sys.argv[1]),
    '-http-address="127.0.0.1:{}"'.format(sys.argv[2])])

print("the commandline is {}".format(proc.args))
proc.wait()
sys.exit(proc.returncode)

输出:

D:\bsm.tar\bsm\final\nsqd>python nsqd.py 4150 4151
the commandline is ['nsqd.exe', '-tcp-address="127.0.0.1:4150"', '-http-address="127.0.0.1:4151"']
[nsqd] 2016/09/26 21:41:51.974681 nsqd v0.3.8 (built w/go1.6.2)
[nsqd] 2016/09/26 21:41:51.975681 ID: 864
[nsqd] 2016/09/26 21:41:51.979675 NSQ: persisting topic/channel metadata to nsqd.864.dat
[nsqd] 2016/09/26 21:41:52.004711 FATAL: listen ("127.0.0.1:4150") failed - listen tcp: lookup "127.0.0.1: getaddrinfow: No such host is known.

如果我 运行 自己直接一切正常:

D:\bsm.tar\bsm\final\nsqd>nsqd.exe -tcp-address="127.0.0.1:4150" -http-address="127.0.0.1:4151"
[nsqd] 2016/09/26 21:42:20.093848 nsqd v0.3.8 (built w/go1.6.2)
[nsqd] 2016/09/26 21:42:20.094850 ID: 864
[nsqd] 2016/09/26 21:42:20.095851 NSQ: persisting topic/channel metadata to nsqd.864.dat
[nsqd] 2016/09/26 21:42:20.127984 TCP: listening on 127.0.0.1:4150
[nsqd] 2016/09/26 21:42:20.127984 HTTP: listening on 127.0.0.1:4151
[nsqd] 2016/09/26 21:42:22.111580 NSQ: persisting topic/channel metadata to nsqd.864.dat
[nsqd] 2016/09/26 21:42:22.111580 TCP: closing 127.0.0.1:4150
[nsqd] 2016/09/26 21:42:22.112553 HTTP: closing 127.0.0.1:4151
[nsqd] 2016/09/26 21:42:22.135635 NSQ: closing topics
[nsqd] 2016/09/26 21:42:22.135635 QUEUESCAN: closing
[nsqd] 2016/09/26 21:42:22.135635 LOOKUP: closing
[nsqd] 2016/09/26 21:42:22.135635 ID: closing

D:\bsm.tar\bsm\final\nsqd>

也许有人知道哪里出了问题?

Win10,python352。 运行 作为管理员没有帮助。

谢谢。

删除 Popen 中的双引号,使其变为:

proc = subprocess.Popen(['nsqd.exe', 
                         '-tcp-address=127.0.0.1:{}'.format(sys.argv[1]), 
                         '-http-address=127.0.0.1:{}'.format(sys.argv[2])
                       ])

在将命令传递给 CreateProcess 之前,Python 使用 subprocess.list2cmdline 将列表转换为字符串:

>>> subprocess.list2cmdline(['nsqd.exe', '-tcp-address="127.0.0.1:4150"', '-http-address="127.0.0.1:4151"'])
'nsqd.exe -tcp-address=\"127.0.0.1:1234\" -http-address=\"127.0.0.1:1234\"

nsqd.exe 认为 "127.0.0.1 是主机名 - 因此查找失败。

附加信息

双引号在命令行上起作用的原因是当使用诸如 CommandLineToArgvW 的函数将命令行拆分为单独的参数时它们具有特殊含义:通常参数由空格分隔,但当遇到带引号的字符串时,引号被去除,整个字符串成为一个参数。

这也是 Python 转义引号的原因:它希望结果行以上述方式解析。

如果你传递 Popen 一个字符串而不是一个列表,list2cmdline 将不会被调用,你应该得到与删除双引号相同的结果(即它会像 运行 从命令行):

proc = subprocess.Popen('nsqd.exe "-tcp-address=127.0.0.1:{}" '
                        '"-http-address=127.0.0.1:{}"'
                        .format(sys.argv[1], sys.argv[2]))

您可以在以下(可能是人为的)示例中看到这一点:

import subprocess
subprocess.Popen('c:\python27\python.exe "--version"')
subprocess.Popen(['c:\python27\python.exe', '"--version"'])

第一个 Popen 将打印 python 版本。第二个将查找名为 "--version" 的文件:can't open file '"--version"': [Errno 22] Invalid argument