如何在python中重载内置模块?

时间:2014-07-25 05:39:20

标签: python sockets

我正在尝试将主机绑定到我的python程序中的指定ips。只是让它在python程序中有效,所以我不打算修改/etc/hosts文件。

我尝试向create_connection中的socket.py函数添加位代码以进行host-ip转换,如下所示:

host, port = address  # the original code in socket.py
# My change here:
if host == "www.google.com":
    host = target_ip  
for res in getaddrinfo(host, port, 0, SOCK_STREAM): # the original code in socket.py

我发现它运作正常。

现在我希望host-ip translation只能在这个python程序中运行。

所以我的问题是:我怎样才能让我的python程序在使用import socket时导入这个socket.py而不是内置的?

为清楚起见,这是一个例子。假设'test'是我的工作目录:

test
|--- main.py
|--- socket.py

在这种情况下:

  1. 如何通过import socket使main.py使用test / socket.py?

  2. 如何让其他模块使用test / socket.py     使用import socket

  3. 我认为更改模块查找路径顺序可能有所帮助。但我发现,即使当前路径('')已经位于sys.path的第一位,import socket仍然会导入内置的scoket模块。

2 个答案:

答案 0 :(得分:4)

在导入可能正在使用它的任何其他模块之前,您可以修补sys.modules,放置自己的模块而不是标准socket

# myscript.py

from myproject import mysocket
import sys
sys.modules['socket'] = mysocket

# ... the rest of your code
import requests
...

为此,mysocket应该公开标准socket所做的一切。

# mysocket.py

import socket as _std_socket
from socket import *  # expose everything

def create_connection(address, *args, **kwargs):
    if address == ...:
       address = ...
    return _std_socket.create_connection(address, *args, **kwargs)

这可能是对mysocket.py应该是什么样的过度简化。你可能需要先添加一些定义才能在生产中使用,但你明白了。


另一种方法是对socket模块本身进行修补,即覆盖原始模块中的名称。

# myscript.py
import socket

def create_connection2(...):
    ...

socket.create_connection = create_connection2

# ... the rest of your code
import requests
...

我更喜欢前一种方法,因为它在某种意义上更清洁,你不需要在里面模块,只是隐藏它并从外面覆盖它中的一些东西。

答案 1 :(得分:1)

您可以使用相对导入在本地使用socket.py模块。但是,要执行此操作,您的项目必须为structured as a package

from . import socket