Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I overload a built-in module in python?

Tags:

python

sockets

I am trying to bind hosts to specified ips in my python program. Just make it affect in the python program, so I am not going to modify the /etc/hosts file.

I tried to add a bit code to the create_connection function in socket.py for host-ip translation, like this:

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

I found it works fine.

And now I want the host-ip translation only works in this python program.

So my question is: how can I make my python program import this socket.py not the build-in one when using import socket?

To make it clear, here is an example. Suppose 'test' is my work directory:

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

In this case:

  1. How can I make main.py use test/socket.py by import socket?

  2. How can I make another modules use test/socket.py when they are using import socket?

I think changing the module find path order may help. But I found that even if the current path('') is in the first place of sys.path already and import socket still imports the built-in scoket module.

like image 449
WKPlus Avatar asked Jul 25 '14 05:07

WKPlus


People also ask

How do you overload in Python?

If we want to implement the concept of function overloading, we need to set the default values of the parameters of the function as None. By setting the value of functional parameters as None, we get the option of calling the function either with or without the parameter.

How do you overload a class in Python?

Python does not support function overloading. When we define multiple functions with the same name, the later one always overrides the prior and thus, in the namespace, there will always be a single entry against each function name.

Can we overload operators in Python?

Python does not limit operator overloading to arithmetic operators only. We can overload comparison operators as well.

Which function overloads >> operator in Python?

7. Which function overloads the >> operator? Explanation: __rshift__() overloads the >> operator.


2 Answers

You can monkey-patch sys.modules, placing your own module instead of the standard socket, before importing any other module which might be using it.

# myscript.py

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

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

For that, mysocket should expose everything which the standard socket does.

# 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)

This might be an over-simplification of what mysocket.py should look like. Youd' likely need to add some definitions before this can be used in production, but you get the idea.


Another approach would be to monkey-patch the socket module itself, i.e. overwrite names inside the original module.

# myscript.py
import socket

def create_connection2(...):
    ...

socket.create_connection = create_connection2

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

I prefer the former approach, becuase it is cleaner in the sense you don't need to go inside the module, only to hide it and override some things in it from the outside.

like image 152
shx2 Avatar answered Sep 28 '22 16:09

shx2


You can use relative imports to locally use a socket.py module. However, to do this your project must be structured as a package.

from . import socket
like image 22
Andrew Johnson Avatar answered Sep 28 '22 17:09

Andrew Johnson