【问题标题】:getaddrinfow fails if running process from Python如果从 Python 运行进程,getaddrinfow 将失败
【发布时间】:2017-02-04 09:30:21
【问题描述】:

我尝试从我的 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。以管理员身份运行没有帮助。

谢谢。

【问题讨论】:

    标签: python windows tcp subprocess nsq


    【解决方案1】:

    删除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

    【讨论】:

    • 任何 Python 都能够处理另一种类型的引号。还是有关于 nsqd.exe 的信息?
    • Python 可以很好地处理嵌套引号。传递给CreateProcess 的确切命令行是subprocess.list2cmdline 给出的命令行。请注意\\" - 引号是斜线转义的,将按字面意思理解。我不是 Windows 人,但我相信转义是由于 CommandLineToArgvW 处理引号的方式。
    • 我愚蠢地认为 nsqd 的 arg 解析器需要这些引号。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多