Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a class in the context of a different module

I want to modify some classes in the standard library to use a different set of globals the ones that other classes in that module use.

Example

This example is an example only:

# module_a.py

my_global = []

class A:
    def __init__(self):
        my_global.append(self)

class B:
    def __init__(self):
        my_global.append(self)

In this example, If I create an instance of A, via A(), it will call append on the object named by my_global. But now I wish to create a new module, import B to it, and have B use my_global from the module it's been imported into, instead of the my_global from the module B was original defined.

# module_b.py

from module_a import B

my_global = []

Related

I'm struggling to explain my problem, here is my previous attempt which did in fact ask something completely different:

  • Clone a module and make changes to the copy

Update0

  • The example above is only for illustration of what I'm trying to achieve.
  • Since there is no variable scope for classes (unlike say, C++), I think a reference to a globals mapping is not stored in a class, but instead is attached to every function when defined.

Update1

An example was requested from the standard library:

Many (maybe all?) of the classes in the threading module make use of globals such as _allocate_lock, get_ident, and _active, defined here and here. One cannot change these globals without changing it for all the classes in that module.

like image 591
Matt Joiner Avatar asked Sep 21 '11 07:09

Matt Joiner


1 Answers

You can't change the globals without affecting all other users of the module, but what you sort of can do is create a private copy of the whole module.

I trust you are familiar with sys.modules, and that if you remove a module from there, Python forgets it was imported, but old objects referencing it will continue to do so. When imported again, a new copy of the module will be made.

A hacky solution to your problem could would be something like this:

import sys
import threading

# Remove the original module, but keep it around
main_threading = sys.modules.pop('threading')

# Get a private copy of the module
import threading as private_threading

# Cover up evidence by restoring the original
sys.modules['threading'] = main_threading

# Modify the private copy
private_threading._allocate_lock = my_allocate_lock()

And now, private_threading.Lock has globals entirely separate from threading.Lock!

Needless to say, the module wasn't written with this in mind, and especially with a system module such as threading you might run into problems. For example, threading._active is supposed to contain all running threads, but with this solution, neither _active will have them all. The code may also eat your socks and set your house on fire, etc. Test rigorously.

like image 157
Petr Viktorin Avatar answered Oct 11 '22 14:10

Petr Viktorin