社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

pyngrok, 一个神奇的 Python 库

程序员老朱 • 1 月前 • 229 次点击  

 

开发时我们常常遇到这样的尴尬:本地写好的 Web 服务、API 或回调接口,只能通过 http://localhost:8000 访问,外网根本够不着。想在手机上调试、想给同事看个演示、想接收第三方平台的 Webhook 回调……都做不了。

ngrok 就是解决这个问题的“内网穿透”神器——它把本地端口映射成一个公网地址。而 pyngrok 是 ngrok 的 Python 封装库,它更进一步:自动下载并管理 ngrok 二进制文件,让你不用手动装 ngrok、不用记命令行参数,直接用 Python 代码就能开隧道。

它的特点:

  • • 自带二进制管理:首次调用会自动下载对应平台的 ngrok,省去手动安装。
  • • 纯 Python API:ngrok.connect() 一行开隧道,返回对象可直接取公网地址。
  • • 兼容 ngrok v2 / v3:默认使用 v3(当前主流)。
  • • 附带命令行:安装后 ngrok 命令也可直接用,原生 CLI 功能全都有。

它非常适合本地开发调试、临时暴露服务、以及 Webhook 联调等场景。

一、安装

用 pip 安装即可:

pip install pyngrok

如果你用 conda:

conda install -c conda-forge pyngrok

先准备一个 authtoken

从 ngrok v3 开始必须认证:你需要去 ngrok 官网 免费注册一个账号,在控制台复制你的 authtoken(形如  2abc...xyz)。这一步是后面所有操作的前提。


最小示例

安装好,我们先在一个终端里起一个本地 HTTP 服务:

python -m http.server 8000

再新建一个 main.py,输入下面代码:

from pyngrok import ngrok

# 设置你的 authtoken(换成你自己的)

ngrok.set_auth_token("你的_AUTHTOKEN")

# 为本地 8000 端口开一条公网隧道

tunnel = ngrok.connect(8000)
print
("公网地址:", tunnel.public_url)

运行脚本:

python main.py

终端会打印出类似 https://xxxx-xx-xx-xx-xx.ngrok-free.app 的地址。把它复制到浏览器打开,你就能从外网访问到本机的 8000 端口服务了。这就是 pyngrok 最直接的能力。

二、具体执行

本节把 pyngrok 的常用能力拆开讲:

  • • 配置身份(authtoken)
  • • 建立隧道(connect() 与 NgrokTunnel)
  • • 选择协议与透传参数
  • • 查看与管理隧道
  • • 高级配置(PyngrokConfig)

2.1 配置 authtoken

有两种等价方式。其一,用 ngrok 官方 CLI 一次性写入配置文件:

ngrok config add-authtoken 你的_AUTHTOKEN

其二,在 Python 里设置(更推荐用于脚本/Colab):

from pyngrok import ngrok

ngrok.set_auth_token("你的_AUTHTOKEN")

set_auth_token() 会把 token 写进 ngrok 配置文件,之后就能使用更多特性(多个并发隧道、自定义域名等)。

小技巧:不要把 token 硬编码进代码,用环境变量读取更安全:

import os
from
 pyngrok import ngrok
ngrok.set_auth_token(os.environ["NGROK_AUTH_TOKEN"])

2.2 建立隧道:connect() 与 NgrokTunnel

ngrok.connect() 的概要签名如下:

ngrok.connect(addr=None, proto=None, name=None, pyngrok_config=None, **options) -> NgrokTunnel

参数说明:

  • • addr:本地地址,可以是端口号(8000 或 "8000")或 "主机:端口"。省略则默认 80。
  • • proto:协议,常用 "http"、"tcp"、"tls"。省略则默认 "http"。
  • • name:从 ngrok 配置文件里启动一个命名隧道。
  • • pyngrok_config:本次调用使用的配置(见 2.5),会覆盖默认值。
  • • **options:其余参数会被透传给 ngrok,如 domain、schemes 等。

它的返回值是一个 NgrokTunnel 对象,公网地址通过 .public_url 获取:

from pyngrok import ngrok

# 打开一个 HTTP 隧道,默认指向 80 端口

http_tunnel = ngrok.connect()
print
(http_tunnel.public_url)      # https://xxxx.ngrok-free.app
print
(http_tunnel.proto)          # http
print
(http_tunnel.config["addr"]) # http://localhost:80

# 打开一个 SSH(TCP)隧道

ssh_tunnel = ngrok.connect("22", "tcp")
print
(ssh_tunnel.public_url)

# 从 ngrok 配置文件里启动命名隧道

named_tunnel = ngrok.connect(name="my-config-file-tunnel")

NgrokTunnel 的常用属性:

  • • public_url:公网访问地址。
  • • proto:协议。
  • • name:隧道名(命名隧道才有)。
  • • config:包含 addr、inspect 等信息的字典。

2.3 选择协议与透传参数

由于 **options 会透传给 ngrok,你几乎可以用上 ngrok 的全部能力:

from pyngrok import ngrok

# 同时暴露 http 与 https

tunnel = ngrok.connect("8000", schemes=["http", "https"])
print
(tunnel.public_url)

# 使用自定义域名(需账号支持)

tunnel = ngrok.connect(addr="9000", domain="my-app.ngrok.app")

# 给隧道加一层 Basic Auth 保护:用户名:密码

tunnel = ngrok.connect("8000, auth="user:pass")
"
"
# 负载均衡的 internal 端点
tunnel = ngrok.connect(
    addr="
9000",
    domain="
some-endpoint.internal",
    pooling_enabled=True,
)

提示:Python 用下划线 pooling_enabled,pyngrok 会自动转换并传给 ngrok。

2.4 查看与管理隧道

from pyngrok import ngrok

# 1. 列出当前所有活动隧道

for
 t in ngrok.get_tunnels():
    print
(f"{t.name}: {t.public_url} -> {t.config['addr']}")

# 2. 关闭指定的某条隧道

tunnel = ngrok.connect("8000")
ngrok.disconnect(tunnel.public_url)

# 3. 关闭本项目下所有 ngrok 进程与隧道

ngrok.kill()

get_ngrok_process() 可以拿到 ngrok 进程对象,它暴露了 api_url(本地管理 API,通常是 http://127.0.0.1:4040)和 proc(底层进程句柄):

from pyngrok import ngrok

ngrok_process = ngrok.get_ngrok_process()
print
("管理 API:", ngrok_process.api_url)

2.5 高级配置:PyngrokConfig

当你需要指定 ngrok 路径、区域、日志回调等,用  PyngrokConfig:

from pyngrok.conf import PyngrokConfig
from
 pyngrok import ngrok, conf

# 方式一:修改全局默认配置

conf.get_default().config_path = "/opt/ngrok/ngrok.yml"  # 自定义配置文件
conf.get_default().region = "us"                         # 区域
conf.get_default().ngrok_version = "v3"                  # ngrok 版本

# 方式二:构造一个配置对象,按需传给 connect()

config = PyngrokConfig(
    ngrok_path="/usr/local/bin/ngrok",  # 指定 ngrok 二进制位置
    region="us",
    startup_timeout=15,                 # 启动超时(秒)
    max_logs=100,
)
tunnel = ngrok.connect("8000", pyngrok_config=config)

PyngrokConfig 常用参数:ngrok_path、config_path、auth_token、region、log_event_callback、startup_timeout、max_logs、request_timeout、ngrok_version。

重要顺序:如果你自定义了 config_path,请先设置 config_path,再调用 set_auth_token(),否则 token 会被写进默认配置文件,导致“设置了却不生效”。

三、优化处理

基础用法掌握后,我们来看几个真实场景里的关键点。

3.1 保活隧道(脚本退出即断线)

这是新手最容易踩的坑:隧道只在 Python 进程存活期间有效 。如果脚本跑完就退出,隧道立刻断开。对于需要常驻的脚本,要阻塞在 ngrok 进程上:

from pyngrok import ngrok

ngrok.set_auth_token("你的_AUTHTOKEN")
tunnel = ngrok.connect("8000")
print
(f"隧道已建立: {tunnel.public_url}")

ngrok_process = ngrok.get_ngrok_process()

try
:
    # 阻塞,直到用户按下 Ctrl+C

    ngrok_process.proc.wait()
except
 KeyboardInterrupt:
    print
("\n正在关闭隧道……")
    ngrok.kill()

3.2 用日志回调实时观测

通过给 PyngrokConfig 传 log_event_callback,可以实时拿到 ngrok 的运行日志,便于调试:

from pyngrok import ngrok
from
 pyngrok.conf import PyngrokConfig

def
 on_log(log):
    # log 对象包含 level、msg 等字段

    print
(f"[ngrok] {log.line} {log.lvl}: {log.msg}")

config = PyngrokConfig(log_event_callback=on_log)
ngrok.set_auth_token("你的_AUTHTOKEN")
tunnel = ngrok.connect("8000", pyngrok_config=config)
print
("公网地址:", tunnel.public_url)

3.3 实战:一行代码暴露本地 Flask 应用

from flask import Flask
from
 pyngrok import ngrok

app = Flask(__name__)

@app.route("/")

def
 index():
    return
 "Hello from Flask, exposed via ngrok!"

if
 __name__ == "__main__":
    ngrok.set_auth_token("你的_AUTHTOKEN")

    # 为本地 5000 端口开隧道

    tunnel = ngrok.connect("5000")
    print
("公网地址:", tunnel.public_url)

    # app.run 会阻塞,保持进程存活,隧道也就一直在线

    app.run(port=5000)

执行结果

四、「注意事项」

1、必须配置 authtoken:ngrok v3 起强制认证,未设置会报认证失败。用 ngrok config add-authtoken 或 ngrok.set_auth_token() 配置。

2、隧道随进程退出而关闭:Python 进程结束,隧道立即断开;常驻脚本需用 proc.wait() 阻塞保活。

3、免费版有限制:公网地址随机且每次重启会变,并有会话时长与请求速率限制;固定/自定义域名通常需要付费套餐(具体以 ngrok 官网当前政策为准)。

4、首次调用会自动下载 ngrok:pyngrok 会把二进制下载到默认路径;在离线或受限网络环境中会失败,可手动放置并用 ngrok_path 指定。

5、config_path 与 token 的顺序:自定义配置文件时,务必先设 config_path 再 set_auth_token,否则 token 写入错误文件。

6、这会真的把服务暴露到公网:隧道等于公开入口,务必加 auth="user:pass" 等保护,用完及时  ngrok.kill()。

 


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/201625