Localproxy-优雅地在Python中使用代理
2024-08-04T06:26:09Z | 2 分钟阅读 | 更新于 2024-08-04T06:26:09Z
Localproxy 使用指南
先上 repo 地址:https://github.com/EvensXia/localproxy
最近因为工作原因,经常需要在代码中访问 HuggingFace,目前访问 HF 主要是通过配置环境变量的方式,以下是常用的几种方法:
常见使用代理的方法
1. 临时使用
命令行直接执行:
export http_proxy=http://proxy-server:port
export https_proxy=https://proxy-server:port
或者:
http_proxy=http://proxy-server:port https_proxy=https://proxy-server:port python xxx.py
2. 配置终端环境变量
将代理设置添加到 .bashrc
文件中:
echo "export http_proxy=http://proxy-server:port" >> ~/.bashrc
echo "export https_proxy=https://proxy-server:port" >> ~/.bashrc
以上方法虽然可以使用,但都不太灵活。临时使用的方式需要每次都要配置脚本,而写死在终端配置里又不能做到细分应用。因此,想设计一个在 Python 中优雅地使用代理的方案。
localproxy
设计思路
我需要一个简单的命令行工具来配置和使用代理,并且能够将配置保存到文件中,人工也方便修改。
需求
- 需要一个cli命令脚本,支持list/set/clear等方式配置代理
- 需要将proxy配置保存到用户目录中(这里需要考虑多系统之间的差异)
- 在代码中能够最简单地调用从而修改环境变量实现代理的使用
- *可以用cli命令执行python代码
实现
-
需求1+4:localproxy/cli.py
这里最开始使用的还是click的方案,后来发现click实现杂糅式的命令行有点复杂,所以改成了原始的
sys.argv
和argparse
,先解析argv[1]
,如果不是.py
的Python脚本,则进入命令行解析; 命令行主要需要支持以下几种形式:localproxy set/list/clear [arg1 arg2] localproxy xxx.py [args...] localproxy -m/-c module.name/"python code" [args...]
解析过程实现(这里还额外增加了
.py
的help说明):def main(): parser = argparse.ArgumentParser( description="Local Proxy CLI\n\n" "To run a Python script directly: \n" " localproxy <script.py> [args]\n\n" "Sub-commands:") subparsers = parser.add_subparsers(dest="command", help="Sub-commands") set_parser = subparsers.add_parser("set", help="Set a proxy configuration") set_parser.add_argument("protocol", type=str, help="Protocol to set (e.g., http, https)") set_parser.add_argument("address", type=str, help="Proxy address (e.g., http://proxy.example.com:8080)") set_parser.set_defaults(func=set_proxy) subparsers.add_parser("list", help="List existing proxy configurations").set_defaults(func=list_proxies) subparsers.add_parser("clear", help="Clear all proxy configurations").set_defaults(func=clear_proxies) parser.add_argument("-m", "--module", nargs="+", help="Module to run") parser.add_argument("-c", "--code", nargs="+", help="Code to run") if len(sys.argv) > 1 and sys.argv[1].endswith(".py"): original_args = sys.argv[1:] run_script(original_args[0], original_args[1:]) else: args, _ = parser.parse_known_args() if args.command == "set": set_proxy(args.protocol, args.address) elif args.command: args.func() elif args.module: run_module(args.module[0], args.module[1:]) elif args.code: run_code(args.code[0], args.code[1:]) else: parser.print_help()
-
需求2+3:localproxy/proxy.py 代码:
import os import toml class ProxyConfig: def __init__(self, config_file): self.config_file = config_file def load(self): """Load proxy configuration from the file.""" if os.path.exists(self.config_file): with open(self.config_file, 'r') as f: return toml.load(f) return {} def save(self, proxies): """Save proxy configuration to the file.""" os.makedirs(os.path.dirname(self.config_file), exist_ok=True) with open(self.config_file, 'w') as f: toml.dump(proxies, f) def init(): """Apply proxy settings to os.environ.""" config = ProxyConfig(os.path.expanduser("~/.local_proxy/proxy.toml")) proxies = config.load() for protocol, address in proxies.items(): os.environ[f"{protocol}_proxy"] = address
这里使用了
os.path.expanduser
和~
符号来确定系统的用户目录; init函数主要提供给导入式的使用方式使用。
使用案例
如在huggingface
中加载squad
数据集,可以这么写:
from datasets import load_dataset
from localproxy import proxy
proxy.init()
load_dataset(path='squad', split="train")
而在cli命令中,就不需要使用额外的代码,以上还可以用这种方式实现:
from datasets import load_dataset
load_dataset(path='squad', split="train")
代码中不使用代理,保存成load_squad.py
命令行中:
localproxy load_squad.py
可以实现同样的应用代理的效果。