推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
starsky007
V2EX  ›  Python

搬运一段 Python 获取局域网 IP 的方法,十分优雅!

  •  
  •   starsky007 · Oct 19, 2021 · 6796 views
    This topic created in 1840 days ago, the information mentioned may be changed or developed.

    代码

    获取局域网 IP,一般做法是先枚举网卡、再获取 IP,但是这种做法的缺点是,不够便携,在不同的机器上需要不同的配置,代码实现上也比较啰嗦。这里搬运一段来自 Stack Overflow 的代码,适用性强、十分优雅。使用 Python 实现,我也就发在 Python 节点了,其他语言也可以借鉴。

    import socket
    def get_ip():
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            # doesn't even have to be reachable
            s.connect(('10.255.255.255', 1))
            IP = s.getsockname()[0]
        except Exception:
            IP = '127.0.0.1'
        finally:
            s.close()
        return IP
    

    来源: networking - Finding local IP addresses using Python's stdlib - Stack Overflow

    应用场景

    比如,DDNS 客户端,如果想要为局域网 IP 绑定域名,往往需要人工选择网卡或者正则表达式匹配域名,我见过的几个 DDNS 客户端比如 No-IP Dynamic Update Client、NewFuture/DDNS 都是这么做的,一般 DDNS 客户端则不支持使用局域网 IP 。如果使用上述代码或思路,就可以方便获取局域网 IP 、简化程序设计、简化用户配置。

    27 replies  •  2021-11-09 15:52:28 +08:00
    proxytoworld
    proxytoworld
    Oct 19, 2021
    1
    这是适用于 网卡和外头连接的,如果有几个网卡,那些网卡不和外界连接的话就没办法了,这个获取本机 IP 的实现在 mirai 木马里面有
    starsky007
    starsky007
    OP
    Oct 19, 2021
    2
    @proxytoworld
    我看原帖里有提到“Works even if all interfaces are unplugged from the network”,即使没有外网连接,也能获取默认路由 IP 。
    adoal
    adoal
    Oct 19, 2021
    3
    “不够便携”……机翻的?
    starsky007
    starsky007
    OP
    Oct 19, 2021
    4
    @adoal
    只有代码是搬运的,其他是我自己写的。protable/便携,意思是,不同环境下只需要配置一次;表达可能有点生硬,您有什么建议?
    princelai
    princelai
    Oct 19, 2021 via Android
    5
    @starsky007 结合上下文,不能在别的机器上用,应该翻译成不便移植更好吧
    simple2025
    simple2025
    Oct 19, 2021❤️1
    6
    这个东西好像不对,如果用了 vpn 的话

    PS D:\ccode\HelloWorld> & C:/Users/Lenovo/AppData/Local/Microsoft/WindowsApps/python3.8.exe d:/ccode/HelloWorld/local.py
    10.110.110.122
    PS D:\ccode\HelloWorld> & C:/Users/Lenovo/AppData/Local/Microsoft/WindowsApps/python3.8.exe d:/ccode/HelloWorld/local.py
    192.168.50.235
    dangyuluo
    dangyuluo
    Oct 20, 2021
    7
    @princelai 现在社会步伐这么快,谁有空来翻译地信雅达
    dingwen07
    dingwen07
    Oct 20, 2021 via iPhone
    8
    socket.gethostbyname(socket.gethostname())
    dingwen07
    dingwen07
    Oct 20, 2021 via iPhone
    9
    #8 盲猜的,没试过
    kokutou
    kokutou
    Oct 20, 2021 via Android❤️4
    10
    局域网 IP❎
    默认路由 IP✅
    raysonx
    raysonx
    Oct 20, 2021 via iPad
    11
    IPv4 only 的。。。。
    skinny
    skinny
    Oct 20, 2021
    12
    10.255.255.255 换成任意 IP 结果也是一样的
    starsky007
    starsky007
    OP
    Oct 20, 2021
    13
    @princelai
    “可移植”一般指的是二进制文件在不同操作系统平台上能运行。
    starsky007
    starsky007
    OP
    Oct 20, 2021
    14
    @chenqh
    好问题。准确地说,代码不是获取局域网 IP,而是获取具有默认路由的本地 IP 。
    starsky007
    starsky007
    OP
    Oct 20, 2021
    15
    @dingwen07
    原帖里其他回答也说了你说的这种写法,是不一样的。
    starsky007
    starsky007
    OP
    Oct 20, 2021
    16
    @kokutou
    👍
    starsky007
    starsky007
    OP
    Oct 20, 2021
    17
    @skinny
    原帖里说了为什么要用 10.255.255.255 ,有差别。
    starsky007
    starsky007
    OP
    Oct 20, 2021
    18
    还是要看一下原帖,帖子只是搬运代码、加了一点点自己的评论,并没有把原帖里面的讨论全部翻译过来。
    ungrown
    ungrown
    Oct 20, 2021❤️1
    19
    @dangyuluo #7 咱也没必要转进到“信达雅”吧,再说“便携”其实挺信达雅的。
    把 portable 这个词用来指代“轻便性”、“自适应性”、“可移植性”或者“自带运行环境无需额外安装”,本来就是类似于比喻的修辞用法,大家觉得这个词表达效果很精妙所以变成了常用语。
    portable 的精髓就是讲究一个“随遇而安”,借用“便携”的表意来表达这份“随意性”、“轻便性”,倒并非刻意指代“移植”,所以直接按照字面意思来翻译就挺好。
    ungrown
    ungrown
    Oct 20, 2021
    20
    我觉得这个函数的局限性还是应该体现在这个帖子的标题当中的,那就是用它写回答的人所表达的那样:它只能获取到设备的“主”IP 地址(也就是附带默认路由的那个地址),而并不能列出所有网络接口上的地址。
    Wincer
    Wincer
    Oct 20, 2021
    21
    试试 psutil 这个库
    starsky007
    starsky007
    OP
    Oct 20, 2021
    22
    @ungrown
    @Wincer
    需求不就是方便快捷地获取默认主 IP 吗?
    julyclyde
    julyclyde
    Oct 20, 2021
    23
    我们这里都是用 magic number 8915 的,嘿嘿
    然后到 mac 上就不行了
    exiaohao
    exiaohao
    Oct 20, 2021
    24
    这个面对大多数情况应该是够了吧,而且是挺巧妙的
    但是如果对 10.255.255.255 这个地址 有什么策略路由或者走的网卡不一样可能会有不一样的结果?赶脚还能用来探测不同地址的不同路由 hh
    skinny
    skinny
    Oct 20, 2021
    25
    @starsky007 原帖说的是广播地址就可以,因为程序不能直接使用广播地址。并不是说一定要 10.255.255.255
    ZeroDu
    ZeroDu
    Oct 21, 2021
    26
    这个不错,在 java 里面怎么实现?
    vanton
    vanton
    Nov 9, 2021
    27
    本地目录装个 psutil ,然后直接用 psutil.net_if_addrs() 不就得了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1363 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 21:59 · PVG 05:59 · LAX 13:59 · JFK 16:59
    ♥ Do have faith in what you're doing.