def test_local_release(): """Locals work without manager""" loc = Local() loc.foo = 42 release_local(loc) assert not hasattr(loc, "foo") ls = LocalStack() ls.push(42) release_local(ls) assert ls.top is None
def __init__(self, app, auto_install=True): self.app = app self.context = LocalStack() if auto_install: logger = getLogger() logger.setLevel(DEBUG) logger.addHandler(self.handler)
def test_coroutine_localstack(self): ctx = LocalStack() patch_local(ctx) @coroutine def other_context(): ctx.push(45) return ctx.top ctx.push(40) fut = asyncio.ensure_future(other_context()) yield from fut self.assertEqual(ctx.top, 40) self.assertNotEqual(ctx.top, fut.result()) self.assertEqual(fut.result(), 45)
def test_custom_idents(): """Local manager supports custom ident functions""" ident = 0 local = Local() stack = LocalStack() mgr = LocalManager([local, stack], ident_func=lambda: ident) local.foo = 42 stack.push({"foo": 42}) ident = 1 local.foo = 23 stack.push({"foo": 23}) ident = 0 assert local.foo == 42 assert stack.top["foo"] == 42 stack.pop() assert stack.top is None ident = 1 assert local.foo == 23 assert stack.top["foo"] == 23 stack.pop() assert stack.top is None
from wsgiref.simple_server import make_server from werkzeug.wrappers import Request as RequestBase, Response as ResponseBase from werkzeug.local import LocalStack, LocalProxy import re import logging as log import json _request_context_stack = LocalStack() request = LocalProxy(lambda: _request_context_stack.top.request) class Request(RequestBase): def __init__(self, environ): RequestBase.__init__(self, environ) class Response(ResponseBase): default_mimetype = 'text/html' class RequestContext(object): def __init__(self, environ): self.request = Request(environ) self.response = Response() def __enter__(self): _request_context_stack.push(self) def __exit__(self, exc_type, exc_val, exc_tb): _request_context_stack.pop()
from flask.signals import template_rendered, request_started, request_finished from webtest import (TestApp as BaseTestApp, TestRequest as BaseTestRequest, TestResponse as BaseTestResponse) try: from flask_sqlalchemy import connection_stack except ImportError: connection_stack = None try: # Available starting with Flask 0.10 from flask.signals import message_flashed except ImportError: message_flashed = None _session_scope_stack = LocalStack() class SessionScope(object): """Session scope, being pushed, changes the value of :func:`.scopefunc` and, as a result, calls to `db.session` are proxied to the new underlying session. When popped, removes the current session and swap the value of :func:`.scopefunc` to the one that was before. :param db: :class:`flask_sqlalchemy.SQLAlchemy` instance """ def __init__(self, db): self.db = db def push(self):
import time import traceback from contextlib import contextmanager import click from click import style from werkzeug.local import LocalProxy from werkzeug.local import LocalStack _reporter_stack = LocalStack() _build_buffer_stack = LocalStack() def describe_build_func(func): self = getattr(func, "__self__", None) if self is not None and any(x.__name__ == "BuildProgram" for x in self.__class__.__mro__): return self.__class__.__module__ + "." + self.__class__.__name__ return func.__module__ + "." + func.__name__ class Reporter(object): def __init__(self, env, verbosity=0): self.env = env self.verbosity = verbosity self.builder_stack = [] self.artifact_stack = [] self.source_stack = [] def push(self):
#引入线程隔离 obj = Local() 这样主进程和子进程就会不相互影响 new_t = threading.Thread(target=worker,name='子进程') new_t.start() 线程隔离的是变量的值 storage{'ident':{'name':'value'}} 6-10 线程隔离的栈:LocalStack 6-11 LocalStack的基本用法 from werkzeug.local import LocalStack 引入实例化 s = LocalStack() 推入栈 s.push(1) 取出栈 s.pop(1) 调用栈顶 s.top 6-12 LocalStack作为线程隔离对象的意义 使当前线程能够正确到引用到他自己所创建的对象,而不是引用到其他线程所创建的对象。 对象是保存变量状态的地方 # 2018-12-03 16:28:22 6-13 flask中被线程隔离的对象 连续发起两次请求,开启前需要打开多线程threading=True @web.route('/test')
=============================== """ from functools import partial from werkzeug.local import LocalProxy, LocalStack class _SharedRequestClass(object): pass def _lookUpObjectInRequestContext(name): top = _requestContextStack.top if top is None: raise RuntimeError('ahixi...') return getattr(top, name) def findApp(): top = _appContextStack.top if top is None: raise RuntimeError('AppContext is none...') return top.app _requestContextStack = LocalStack() _appContextStack = LocalStack() currentApp = LocalProxy(findApp) request = LocalProxy(partial(_lookUpObjectInRequestContext, 'request')) session = LocalProxy(partial(_lookUpObjectInRequestContext, 'session')) shared = LocalProxy(partial(_lookUpObjectInRequestContext, 'shared'))
""" Created by ZZXUN on 2018/8/6 """ import threading import time from werkzeug.local import Local, LocalStack __author__ = "ZZXUN" class A: b = 1 my_job = LocalStack() my_job.push(1) # 两个线程实例化两个栈,彼此数据不干扰 def worker(): print("in new thread before push, value is :" + str(my_job.top)) my_job.push(2) print("in new thread after push, value is :" + str(my_job.top)) new_t = threading.Thread(target=worker, name="zzx") new_t.start() time.sleep(1)
# coding=utf-8 import random from flask import Flask, g, render_template from chapter3.section3.ext import db from chapter3.section3.users import User from werkzeug.local import LocalProxy, LocalStack app = Flask(__name__, template_folder='../../templates') app.config.from_object('chapter3.section3.config') db.init_app(app) _user_stack = LocalStack() def get_current_user(): top = _user_stack.top if top is None: raise RuntimeError() return top current_user = LocalProxy(get_current_user) @app.before_first_request def setup(): db.drop_all() db.create_all() fake_users = [ User('xiaoming'), User('dongqihong'),
from functools import partial from werkzeug.local import LocalProxy, LocalStack def _find_request_obj(name): top = _request_stack.top return getattr(top, name) def _find_app_obj(name): top = _app_stack.top return getattr(top, name) def _get_app(): top = _app_stack.top return top.app _request_stack = LocalStack() _app_stack = LocalStack() current_app = LocalProxy(_get_app) request = LocalProxy(partial(_find_request_obj, 'request')) session = LocalProxy(partial(_find_request_obj, 'session')) g = LocalProxy(partial(_find_app_obj, 'g'))
from blinker import Namespace from sqlalchemy import orm, event, inspect from sqlalchemy.orm.exc import UnmappedClassError from sqlalchemy.orm.session import Session as SessionBase from sqlalchemy.engine.url import make_url from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta from werkzeug.local import LocalStack from ._compat import string_types, itervalues # the best timer function for the platform if sys.platform == 'win32': _timer = time.clock else: _timer = time.time connection_stack = LocalStack() _camelcase_re = re.compile(r'([A-Z]+)(?=[a-z0-9])') _signals = Namespace() models_committed = _signals.signal('models-committed') before_models_committed = _signals.signal('before-models-committed') def _calling_context(app_path): frm = sys._getframe(1) while frm.f_back is not None: name = frm.f_globals.get('__name__') if name and (name == app_path or name.startswith(app_path + '.')): funcname = frm.f_code.co_name return '%s:%s (%s)' % (
# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Manage local contexts.""" from contextlib import contextmanager import attr from werkzeug.local import LocalStack _current_reference = LocalStack() current_reference = _current_reference() @contextmanager def with_reference(path): """Manage reference stack.""" _current_reference.push(path) yield if path != _current_reference.pop(): raise RuntimeError('current_reference has been modified') def has_reference(): """Check if the current reference is bounded."""
# 装饰器部分 import functools import json from flask import request from sqlalchemy.orm import joinedload from werkzeug.local import LocalStack, LocalProxy from app.models import Account, Employee, Enterprise from app.response import custom account_stack = LocalStack() employee_stack = LocalStack() enterprise_stack = LocalStack() current_account = LocalProxy(lambda: account_stack.top) current_employee = LocalProxy(lambda: employee_stack.top) current_enterprise = LocalProxy(lambda: enterprise_stack.top) def check_params(func): @functools.wraps(func) def wrapper(*args, **kwargs): if func.__doc__: params = json.loads(func.__doc__) if request.method == "GET": for param in params: status, msg, data = check_required_and_type( param, request.args.get(param["name"])) if not status:
#-*- coding:utf-8 _*- """ @author:star @file: test7.py @time: 2018/08/12 """ from werkzeug.local import LocalStack, LocalProxy user_stack = LocalStack() user_stack.push({'name': 'alice'}) user_stack.push({'name': 'bob'}) def get_user(): return user_stack.pop() user = LocalProxy(get_user) print(user.get('name')) print(user.get('name'))
from werkzeug.local import Local, LocalStack, LocalProxy ls = LocalStack() ls.push(42) print(ls.top) ls.push(23) print(ls.top) print(ls.pop()) print(ls.top)
from contextlib import contextmanager from werkzeug.local import LocalStack _workers_stack = LocalStack() worker_ctx = _workers_stack() @contextmanager def push_worker_ctx(worker_ctx_): _workers_stack.push(worker_ctx_) try: yield worker_ctx_ finally: _workers_stack.pop()
from werkzeug.local import LocalStack, LocalProxy test_stack = LocalStack() test_stack.push({"abc": "123"}) test_stack.push({"abc": "1234"}) def get_item(): return test_stack.pop() # LocalProxy 需要初始化callable的对象,然后每次调用proxy时 内部会去call一次这个初始化对象。 item = LocalProxy(get_item) print(item["abc"]) print(item["abc"])
# This file is part of Flask-PluginEngine. # Copyright (C) 2014-2017 CERN # # Flask-PluginEngine is free software; you can redistribute it # and/or modify it under the terms of the Revised BSD License. from werkzeug.local import LocalStack, LocalProxy _plugin_ctx_stack = LocalStack() #: Proxy to the currently active plugin current_plugin = LocalProxy(lambda: _plugin_ctx_stack.top)
class wsgiApp: __config = None logger = None def __init__(self): self.__url_map = Map([ Rule('/', endpoint='hello') # Rule('/<short_id>', endpoint='follow_short_link'), # Rule('/<short_id>+', endpoint='short_link_details') ]) self.logger = loadLogging(self.logger) self.is_run = False self.__view_functions = dict() self.__localstack = LocalStack() self.__read_config() def __read_config(self): if self.__config is None: configp = ConfigParser(allow_no_value=True) dirlist = os.listdir(os.getcwd() + '\\config') config_files = list() for dirname in dirlist: if dirname.endswith('.ini'): config_files.append(dirname) self.__config = dict() for config_file in config_files: configp.read(os.getcwd() + '\\config\\' + config_file) sections = configp.sections() for section in sections: item = dict() for key, value in configp.items(section): item[key] = value self.__config[section] = item def get_config(self): if self.__config is None: self.__read_config() return self.__config def run(self): if self.is_run is True: print 'the app is already running' else: config = self.get_config() run_simple(hostname=config['BaseConfig']['hostname'], port=int(config['BaseConfig']['port']), application=self) self.is_run = True def get_data(self, request): if request.method.lower() == 'post': data = request.form.to_dict() else: data = request.args.to_dict() writeLogging(self.logger, 'get request:' + str(data)) return data def get_local_attr(self, attr): local_attr = LocalProxy(self.__localstack.top[attr]) return local_attr def get_request(self): return self.get_local_attr('request') def __push_local_attr(self, local_attr): def get_it(): return local_attr return get_it def __call__(self, environ, start_response): request = Request(environ) self.__localstack.push({"request": self.__push_local_attr(request)}) adapter = self.__url_map.bind_to_environ(request.environ) try: endpoint, values = adapter.match() status = 200 if endpoint in self.__view_functions: res = self.__view_functions[endpoint]() else: res = getattr(self, 'on_' + endpoint)(request) except NotFound, e: status = 404 res = e.get_body() except MethodNotAllowed, e: status = 405 res = e.get_body()
def get_app_ctx_obj(name): top = _app_ctx_content.top if top is None: raise RuntimeError(app_ctx_error_msg) return getattr(top, name) def get_current_app(): top = _app_ctx_content.top if top is None: raise RuntimeError(app_ctx_error_msg) return top.app def has_app_ctx(): return _app_ctx_content.top is not None def has_request_ctx(): return _request_ctx_content.top is not None _request_ctx_content = LocalStack() _app_ctx_content = LocalStack() request = LocalProxy(partial(get_request_obj, 'request')) session = LocalProxy(partial(get_request_obj, 'session')) g = LocalProxy(partial(get_app_ctx_obj, 'g')) current_app = LocalProxy(get_current_app)
from flask import current_app, json, request as flask_request, _app_ctx_stack from . import verifier from . import logger from .convert import to_date, to_time, to_timedelta import collections import random from . import models request = LocalProxy(lambda: current_app.ask.request) session = LocalProxy(lambda: current_app.ask.session) version = LocalProxy(lambda: current_app.ask.version) context = LocalProxy(lambda: current_app.ask.context) convert_errors = LocalProxy(lambda: current_app.ask.convert_errors) current_stream = LocalProxy(lambda: current_app.ask.current_stream) _stream_buffer = LocalStack() _converters = {'date': to_date, 'time': to_time, 'timedelta': to_timedelta} class Ask(object): """The Ask object provides the central interface for interacting with the Alexa service. Ask object maps Alexa Requests to flask view functions and handles Alexa sessions. The constructor is passed a Flask App instance, and URL endpoint. The Flask instance allows the convienient API of endpoints and their view functions, so that Alexa requests may be mapped with syntax similar to a typical Flask server. Route provides the entry point for the skill, and must be provided if an app is given. Keyword Arguments: app {Flask object} -- App instance - created with Flask(__name__) (default: {None})
from contextlib import contextmanager from functools import wraps from werkzeug.local import LocalProxy, LocalStack _additional_ctx_stack = LocalStack() __all__ = ("current_additions", "Additional", "AdditionalManager") @LocalProxy def current_additions(): """ Proxy to the currently added requirements """ rv = _additional_ctx_stack.top if rv is None: return None return rv[1] def _isinstance(f): @wraps(f) def check(self, other): if not isinstance(other, Additional): return NotImplemented return f(self, other) return check
def _lookup_log_object(name): top = _log_ctx_stack.top if top is None: raise RuntimeError('Running outside of log context') return getattr(top, name) def _lookup_scan_object(name): top = _scan_ctx_stack.top if top is None: raise RuntimeError('Running outside of scan context') return getattr(top, name) def _lookup_node_object(name): top = _node_ctx_stack.top if top is None: raise RuntimeError('Running outside of node context') return getattr(top, name) _log_ctx_stack = LocalStack() _scan_ctx_stack = LocalStack() _node_ctx_stack = LocalStack() log_debug = LocalProxy(partial(_lookup_log_object, 'debug')) log_info = LocalProxy(partial(_lookup_log_object, 'info')) log_warn = LocalProxy(partial(_lookup_log_object, 'warn')) log_error = LocalProxy(partial(_lookup_log_object, 'error')) make_fileset = LocalProxy(partial(_lookup_scan_object, 'make_fileset')) make_file = LocalProxy(partial(_lookup_node_object, 'make_file'))
from werkzeug.local import LocalProxy, LocalStack from jinja2 import BaseLoader, ChoiceLoader, TemplateNotFound from flask import current_app, json, request as flask_request, _app_ctx_stack from . import verifier from . import logger from .convert import to_date, to_time, to_timedelta import collections import random request = LocalProxy(lambda: current_app.ask.request) session = LocalProxy(lambda: current_app.ask.session) version = LocalProxy(lambda: current_app.ask.version) context = LocalProxy(lambda: current_app.ask.context) convert_errors = LocalProxy(lambda: current_app.ask.convert_errors) current_stream = LocalStack() _converters = {'date': to_date, 'time': to_time, 'timedelta': to_timedelta} class Ask(object): """The Ask object provides the central interface for interacting with the Alexa service. Ask object maps Alexa Requests to flask view functions and handles Alexa sessions. The constructor is passed a Flask App instance, and URL endpoint. The Flask instance allows the convienient API of endpoints and their view functions, so that Alexa requests may be mapped with syntax similar to a typical Flask server. Route provides the entry point for the skill, and must be provided if an app is given. Keyword Arguments: app {Flask object} -- App instance - created with Flask(__name__) (default: {None})
from jinja2 import Undefined from contextlib import contextmanager from werkzeug.local import LocalStack, LocalProxy from lektor.reporter import reporter _ctx_stack = LocalStack() def url_to(*args, **kwargs): """Calculates a URL to another record.""" ctx = get_ctx() if ctx is None: raise RuntimeError('No context found') return ctx.url_to(*args, **kwargs) def get_asset_url(asset): """Calculates the asset URL relative to the current record.""" ctx = get_ctx() if ctx is None: raise RuntimeError('No context found') asset = site_proxy.get_asset(asset) if asset is None: return Undefined('Asset not found') info = ctx.build_state.get_file_info(asset.source_filename) return '%s?h=%s' % ( ctx.source.url_to('!' + asset.url_path), info.checksum[:8], )
if self in r: self._handle_request_noblock() 当有请求进来后触发处理当前请求的逻辑,这是调用__call__的第一步 但其绑定是在run方法中的run_simple中 """ print("environ:", environ) print("start_response:", start_response) return self.wsgi_app(environ, start_response) ################################################################### # 全局上下文变量定义(context locals) # 说明: # - 此处全局的 g, session, 需要深入理解 # - 需要深入去看 werkzeug.LocalStack() 的实现 Local-->LocalStack-->LocalProxy 这三个的关系参考下面的链接 # https://www.jianshu.com/p/3f38b777a621,https://blog.csdn.net/barrysj/article/details/51519254 # python中有threading local处理方式,在多线程环境中将变量按照线程id区分,由于协程在Python web中广泛使用,所以threading local不再满足需要 # local中优先使用greenlet协程,其次是线程id。localstack相当于在本协程(线程)中将数据以stack的形式存储(通过封装local来实现)。 # LocalProxy就是local的代理。重载了很多运算符,方便变量值得动态更新和获取, # ################################################################### _request_ctx_stack = LocalStack() # 依赖 werkzeug.LocalStack 模块-->`Local`堆栈 current_app = LocalProxy(lambda: _request_ctx_stack.top.app) request = LocalProxy(lambda: _request_ctx_stack.top.request) # - g: 请求上下文 栈对象 # - session: 请求上下文 栈对象 session = LocalProxy(lambda: _request_ctx_stack.top.session) # flash()函数中引用 g = LocalProxy(lambda: _request_ctx_stack.top.g)
def _lookup_req_object(name): top = _request_ctx_stack.top if top is None: raise RuntimeError(_request_ctx_err_msg) return getattr(top, name) def _lookup_app_object(name): top = _app_ctx_stack.top if top is None: raise RuntimeError(_app_ctx_err_msg) return getattr(top, name) def _find_app(): top = _app_ctx_stack.top if top is None: raise RuntimeError(_app_ctx_err_msg) return top.app # context locals _request_ctx_stack = LocalStack() _app_ctx_stack = LocalStack() current_app = LocalProxy(_find_app) request = LocalProxy(partial(_lookup_req_object, "request")) session = LocalProxy(partial(_lookup_req_object, "session")) g = LocalProxy(partial(_lookup_app_object, "g"))
class Context(LocalStack): pass def _lookup_context(): top = _context_stack.top if top is None: raise RuntimeError('Working outside of browser context.') return top def _copy_or_create_context(): if _context_stack.top: return copy(_context_stack.top) else: return Context() @contextmanager def browser_context(): context = _copy_or_create_context() _context_stack.push(context) try: yield finally: _context_stack.pop() _context_stack = LocalStack() context = LocalProxy(_lookup_context)
from werkzeug.local import LocalStack import threading import time # push pop top my_stack=LocalStack() my_stack.push(1) print('in main thread after push ,value is :'+str(my_stack.top)) def worker(): print('in new thread befor push ,value is:'+str(my_stack.top)) my_stack.push(3) print('in new thread after push ,value is :'+str(my_stack.top)) new_t=threading.Thread(target=worker(),name='qiyue_thread') new_t.start() time.sleep(1) print('finally,in main thread values is : '+str(my_stack.top))
# push,pop,top # s = LocalStack() # s.push(1) # print(s.top) # print(s.top) # print(s.pop()) # print(s.pop()) # # s.push(1) # s.push(2) # print(s.top) #2 # print(s.top)#2 # print(s.pop()) #2 # print(s.top) #1 my_stack = LocalStack() my_stack.push(1) print("in main thread after push, value is:" + str(my_stack.top)) # 1 def work(): # new スレッド print("in new thread before push, value is:" + str(my_stack.top)) # 1 my_stack.push(2) print("in new thread after push, value is:" + str(my_stack.top)) # 2 new_t = threading.Thread(target=work, name="qiyue_thread") new_t.start() time.sleep(1)
def __init__(self, old_stack=None): LocalStack.__init__(self) if not old_stack is None: self._local = old_stack._local self.__ident_func__ = self.get_parent_id
# def __setattr__(self, key, value): # # self.__storage__[key] = value # pass # def query(self): # return self.__storage__ # # local = Local() # local.__storage__['hah'] = 1 # print(local.query()) # print(local.hah) from werkzeug.local import LocalStack import threading import time stack = LocalStack() stack.push(1) print('main thread value is {}'.format(stack.top)) def work(): print('{} value is {}'.format(threading.current_thread().name, stack.top)) stack.push(2) print('{} value is {}'.format(threading.current_thread().name, stack.top)) if __name__ == '__main__': t = threading.Thread(target=work, name='lee') t.start() time.sleep(1) print('main thread value is {}'.format(stack.top))
class LoggingMiddleware(object): def __init__(self, app, auto_install=True): self.app = app self.context = LocalStack() if auto_install: logger = getLogger() logger.setLevel(DEBUG) logger.addHandler(self.handler) @cached_property def handler(self): return WSGIHandler(self) def __call__(self, environ, start_response): html = [False] def start(status, headers, exc_info=None): headers = list(headers) replaced_headers = [] for k, v in headers: name = k.lower().strip() if name == 'content-type': content_type = v.lower().split(';')[0] content_type = content_type.strip().lower() html[0] = content_type == 'text/html' if name != 'content-length': replaced_headers.append((k, v)) return start_response(status, replaced_headers) self.context.push([]) result = self.app(environ, start) result = list(result) if html[0]: return self.inject_log_html(result) return result def inject_log_html(self, iterable): injected = False for chunk in iterable: if not injected and '</body>' in chunk: a, b = chunk.split('</body>', 1) yield a for subchunk in self.log_html(): yield subchunk yield b injected = True else: yield chunk if not injected: for chunk in self.log_html(): yield chunk def log_html(self): level_map = {DEBUG: 'debug', INFO: 'info', WARNING: 'warn', ERROR: 'error', CRITICAL: 'error'} records = self.context.pop() yield '<script>\n//<![CDATA[\nif (console) {\n' for record in records: yield 'console.' yield level_map[record.levelno] yield '(' yield dumps(record.name) yield ' + ": " + ' yield dumps(str(record.getMessage())) yield ');' yield '\n}\n// ]]>\n</script>'
from werkzeug.local import LocalStack # push、pop、top # 实例化一个对象 s = LocalStack() # 把一个元素推入到栈顶 s.push(1) # 读取栈顶元素、top是一个属性 print(s.top) print(s.top) # 弹出栈顶元素、pop是一个方法 print(s.pop()) print(s.top) # 推入两个元素 s.push(1) s.push(2) # 栈 后进先出 print(s.top) print(s.top) print(s.pop()) print(s.top) # 2 # 2 # 2
def test_local_stack(): """Test the LocalStack""" ident = get_ident() ls = LocalStack() assert ident not in ls._local.__storage__ assert ls.top is None ls.push(42) assert ident in ls._local.__storage__ assert ls.top == 42 ls.push(23) assert ls.top == 23 ls.pop() assert ls.top == 42 ls.pop() assert ls.top is None assert ls.pop() is None assert ls.pop() is None proxy = ls() ls.push([1, 2]) assert proxy == [1, 2] ls.push((1, 2)) assert proxy == (1, 2) ls.pop() ls.pop() assert repr(proxy) == "<LocalProxy unbound>" assert ident not in ls._local.__storage__
# -*- coding: utf-8 -*- import gettext from babel import support from babel.support import NullTranslations from flask import current_app from werkzeug.local import LocalStack, LocalProxy import os.path _translation_stack = LocalStack() class TranslationContextBase(object): def __init__(self): self._refcnt = 0 def push(self): self._refcnt += 1 _translation_stack.push(self) def pop(self): self._refcnt -= 1 rv = _translation_stack.pop() assert rv is self, 'Popped wrong translation context. (%r instead of %r)' \ % (rv, self) def __enter__(self): self.push() return self def __exit__(self, exc_type, exc_value, tb):
print(f'In {current_thread().name} {obj.__ident_func__()} obj.a is', obj.a) def manipulate(): obj.a = 2 print(f'In {current_thread().name} {obj.__ident_func__()} obj.a is', obj.a) newThread = Thread(name='newThread', target=manipulate) newThread.start() time.sleep(1) print(f'In {current_thread().name} {obj.__ident_func__()} obj.a is', obj.a) # 线程隔离栈的试验 stk = LocalStack() stk.push(1) print(f'In {current_thread().name} {stk._local.__ident_func__()} stk.top is', stk.top) def manipulateStack(): print( f'In {current_thread().name} {stk._local.__ident_func__()} stk.top is', stk.top) newTread2 = Thread(name='newThread2', target=manipulateStack) newTread2.start() time.sleep(1)