如果从Python运行进程,getaddrinfow会失败

时间:2016-09-26 21:52:07

标签: python windows tcp subprocess nsq

我尝试从我的python脚本运行第三方进程(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。以管理员身份运行无济于事。

感谢。

1 个答案:

答案 0 :(得分:2)

删除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是\ -escap引号:它期望以上述方式解析结果行。

如果你传递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