0

我尝试从我的 python 脚本运行 3rd 方进程 (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。以管理员身份运行没有帮助。

谢谢。

4

1 回答 1

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 对引号进行 \-转义的原因:它希望以上述方式解析结果行。

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

于 2016-09-26T23:22:07.853 回答