अजगर मानक lib (विशेष रूप से @deprecated) में सज्जाकार


127

मुझे पदावनत के रूप में रूटीन को चिह्नित करने की आवश्यकता है, लेकिन जाहिर है कि पदावनत के लिए कोई मानक पुस्तकालय डेकोरेटर नहीं है। मैं इसके लिए व्यंजनों और चेतावनी मॉड्यूल से अवगत हूं, लेकिन मेरा सवाल यह है: इस (आम) कार्य के लिए कोई मानक पुस्तकालय सज्जाकार क्यों नहीं है?

अतिरिक्त प्रश्न: क्या मानक पुस्तकालय में मानक सज्जाकार हैं?


13
अब एक पदावनति पैकेज है
muon

11
मैं इसे करने के तरीकों को समझता हूं, लेकिन यहां कुछ अंतर्दृष्टि के लिए आया हूं कि यह एसटीडी लिब में क्यों नहीं है (जैसा कि मैं मान रहा हूं कि ओपी का मामला है) और वास्तविक प्रश्न का एक अच्छा जवाब नहीं दिखता है
SwimBikeRun

4
ऐसा अक्सर क्यों होता है कि प्रश्नों के दर्जनों उत्तर मिलते हैं जो प्रश्न का उत्तर देने का प्रयास भी नहीं करते हैं, और "मैं व्यंजनों से अवगत हूं" जैसी चीजों को सक्रिय रूप से अनदेखा करता हूं? यह पागलपन है!
कैटस्कुल

1
@ नकली इंटरनेट पॉइंट्स की वजह से कैटकुल।
स्टेफानो बोरीनी

1
आप डिप्रेस्ड लाइब्रेरी का उपयोग कर सकते हैं ।
लॉरेंट LAPORTE

जवाबों:


59

यहाँ कुछ स्निपेट दिए गए हैं, जो लिएंडरो द्वारा उद्धृत किए गए हैं:

import warnings
import functools

def deprecated(func):
    """This is a decorator which can be used to mark functions
    as deprecated. It will result in a warning being emitted
    when the function is used."""
    @functools.wraps(func)
    def new_func(*args, **kwargs):
        warnings.simplefilter('always', DeprecationWarning)  # turn off filter
        warnings.warn("Call to deprecated function {}.".format(func.__name__),
                      category=DeprecationWarning,
                      stacklevel=2)
        warnings.simplefilter('default', DeprecationWarning)  # reset filter
        return func(*args, **kwargs)
    return new_func

# Examples

@deprecated
def some_old_function(x, y):
    return x + y

class SomeClass:
    @deprecated
    def some_old_method(self, x, y):
        return x + y

क्योंकि कुछ दुभाषियों में पहला समाधान उजागर (बिना फिल्टर हैंडलिंग) के परिणामस्वरूप चेतावनी दमन हो सकता है।


14
functools.wrapsनाम सेट करने और डॉक की तरह उपयोग करने के बजाय क्यों नहीं ?
मैक्सिमिलियन

1
@Maximilian: इस कोड के भावी कॉपी-पेस्टर्स को गलत करने से बचाने के लिए, इसे जोड़ने के लिए संपादित किया गया
Eric

17
मुझे साइड इफेक्ट (फिल्टर चालू / बंद करना) पसंद नहीं है। यह तय करना डेकोरेटर का काम नहीं है।
केंटो

1
फ़िल्टर को चालू और बंद करना बग्सिपेथोन.org
gerrit

4
वास्तविक प्रश्न का उत्तर नहीं देता है।
कैटस्कुल

44

यहाँ एक और उपाय है:

यह डेकोरेटर (एक सजाने वाला कारखाना) वास्तव में ) आपको एक कारण संदेश देने की अनुमति देता है । स्रोत फ़ाइल नाम और लाइन नंबर देकर समस्या का निदान करने में मदद करने के लिए यह अधिक उपयोगी है ।

EDIT : यह कोड शून्य की सिफारिश का उपयोग करता है: यह warnings.warn_explicitलाइन को प्रतिस्थापित करता है warnings.warn(msg, category=DeprecationWarning, stacklevel=2), जो फ़ंक्शन परिभाषा साइट के बजाय फ़ंक्शन कॉल साइट को प्रिंट करता है। यह डिबगिंग को आसान बनाता है।

EDIT2 : यह संस्करण डेवलपर को एक वैकल्पिक "कारण" संदेश निर्दिष्ट करने की अनुमति देता है।

import functools
import inspect
import warnings

string_types = (type(b''), type(u''))


def deprecated(reason):
    """
    This is a decorator which can be used to mark functions
    as deprecated. It will result in a warning being emitted
    when the function is used.
    """

    if isinstance(reason, string_types):

        # The @deprecated is used with a 'reason'.
        #
        # .. code-block:: python
        #
        #    @deprecated("please, use another function")
        #    def old_function(x, y):
        #      pass

        def decorator(func1):

            if inspect.isclass(func1):
                fmt1 = "Call to deprecated class {name} ({reason})."
            else:
                fmt1 = "Call to deprecated function {name} ({reason})."

            @functools.wraps(func1)
            def new_func1(*args, **kwargs):
                warnings.simplefilter('always', DeprecationWarning)
                warnings.warn(
                    fmt1.format(name=func1.__name__, reason=reason),
                    category=DeprecationWarning,
                    stacklevel=2
                )
                warnings.simplefilter('default', DeprecationWarning)
                return func1(*args, **kwargs)

            return new_func1

        return decorator

    elif inspect.isclass(reason) or inspect.isfunction(reason):

        # The @deprecated is used without any 'reason'.
        #
        # .. code-block:: python
        #
        #    @deprecated
        #    def old_function(x, y):
        #      pass

        func2 = reason

        if inspect.isclass(func2):
            fmt2 = "Call to deprecated class {name}."
        else:
            fmt2 = "Call to deprecated function {name}."

        @functools.wraps(func2)
        def new_func2(*args, **kwargs):
            warnings.simplefilter('always', DeprecationWarning)
            warnings.warn(
                fmt2.format(name=func2.__name__),
                category=DeprecationWarning,
                stacklevel=2
            )
            warnings.simplefilter('default', DeprecationWarning)
            return func2(*args, **kwargs)

        return new_func2

    else:
        raise TypeError(repr(type(reason)))

आप इस डेकोरेटर का उपयोग कार्यों के लिए कर सकते हैं , विधियों और कक्षाओं के

ये रहा एक सरल उदाहरण:

@deprecated("use another function")
def some_old_function(x, y):
    return x + y


class SomeClass(object):
    @deprecated("use another method")
    def some_old_method(self, x, y):
        return x + y


@deprecated("use another class")
class SomeOldClass(object):
    pass


some_old_function(5, 3)
SomeClass().some_old_method(8, 9)
SomeOldClass()

आपको मिलेगा:

deprecated_example.py:59: DeprecationWarning: Call to deprecated function or method some_old_function (use another function).
  some_old_function(5, 3)
deprecated_example.py:60: DeprecationWarning: Call to deprecated function or method some_old_method (use another method).
  SomeClass().some_old_method(8, 9)
deprecated_example.py:61: DeprecationWarning: Call to deprecated class SomeOldClass (use another class).
  SomeOldClass()

EDIT3: यह डेकोरेटर अब लाइब्रेरी का हिस्सा है:

नई स्थिर रिलीज v1.2.10 .10


6
कार्य करता है, अच्छी तरह से - मैं उस warn_explicitपंक्ति को बदलना पसंद करता हूं warnings.warn(msg, category=DeprecationWarning, stacklevel=2)जिसके साथ फ़ंक्शन परिभाषा साइट के बजाय फ़ंक्शन कॉल साइट को प्रिंट करता है। यह डिबगिंग को आसान बनाता है।
ज़ीरो

नमस्कार, मैं GPLv3- लाइसेंस वाली लाइब्रेरी में आपके कोड स्निपेट का उपयोग करना चाहूंगा । क्या आप GPLv3 या किसी और अनुज्ञप्ति लाइसेंस के तहत अपने कोड को पुनः प्राप्त करने के लिए तैयार होंगे , ताकि मैं कानूनी रूप से ऐसा कर सकूं?
जेरिट


1
@LaurentLAPORTE मुझे पता है। CC-BY-SO GPLv3 (शेयर-समान बिट के कारण) के भीतर उपयोग की अनुमति नहीं देता है, यही कारण है कि मैं पूछ रहा हूं कि क्या आप इस कोड को विशेष रूप से GPL- संगत लाइसेंस के तहत जारी करने के लिए तैयार होंगे। यदि नहीं, तो यह ठीक है, और मैं आपके कोड का उपयोग नहीं करूंगा।
जेरिट

2
वास्तविक प्रश्न का उत्तर नहीं देता है।
कैटस्कुल

15

जैसा कि मुऑन ने सुझाव दिया है , आप इसके लिए deprecationपैकेज स्थापित कर सकते हैं ।

deprecationपुस्तकालय एक प्रदान करता है deprecatedडेकोरेटर और एक fail_if_not_removedअपने परीक्षण के लिए डेकोरेटर।

स्थापना

pip install deprecation

उदाहरण उपयोग

import deprecation

@deprecation.deprecated(deprecated_in="1.0", removed_in="2.0",
                        current_version=__version__,
                        details="Use the bar function instead")
def foo():
    """Do some stuff"""
    return 1

पूर्ण प्रलेखन के लिए http://deprecation.readthedocs.io/ देखें ।


4
वास्तविक प्रश्न का उत्तर नहीं देता है।
कैटस्कूल

1
नोट PyCharm इसे नहीं पहचानता है
cz

11

मुझे लगता है कि इसका कारण यह है कि पायथन कोड को वैधानिक रूप से संसाधित नहीं किया जा सकता है (जैसा कि यह C ++ कंपाइलर के लिए किया गया है), आप वास्तव में इसका उपयोग करने से पहले कुछ चीजों का उपयोग करने के बारे में चेतावनी नहीं प्राप्त कर सकते हैं। मुझे नहीं लगता है कि संदेशों का एक समूह "चेतावनी: यह स्क्रिप्ट के डेवलपर डेप्रिसिएटेड एपीआई का उपयोग कर रहा है" के साथ अपनी स्क्रिप्ट के उपयोगकर्ता को स्पैम करने के लिए एक अच्छा विचार है।

अपडेट: लेकिन आप डेकोरेटर बना सकते हैं जो मूल फ़ंक्शन को दूसरे में बदल देगा। नया फ़ंक्शन स्विच / चेक को यह बताएगा कि यह फ़ंक्शन पहले ही कॉल किया गया था और स्विच ऑन स्टेट पर केवल संदेश दिखाएगा। और / या बाहर निकलने पर यह कार्यक्रम में उपयोग किए गए सभी पदावनत कार्यों की सूची प्रिंट कर सकता है।


3
और जब आप मॉड्यूल से फ़ंक्शन आयात करते हैं तो आपको डेप्रिसिएशन इंगित करने में सक्षम होना चाहिए । डेकोरेटर उस के लिए एक सही उपकरण होगा।
Janusz Lenar

@JanuszLenar, यह चेतावनी तब भी दिखाई जाएगी जब हम उस पदावनत समारोह का उपयोग नहीं करते हैं। लेकिन मुझे लगता है कि मैं अपने जवाब को कुछ संकेत के साथ अपडेट कर सकता हूं।
ony

8

आप एक बर्तन फ़ाइल बना सकते हैं

import warnings

def deprecated(message):
  def deprecated_decorator(func):
      def deprecated_func(*args, **kwargs):
          warnings.warn("{} is a deprecated function. {}".format(func.__name__, message),
                        category=DeprecationWarning,
                        stacklevel=2)
          warnings.simplefilter('default', DeprecationWarning)
          return func(*args, **kwargs)
      return deprecated_func
  return deprecated_decorator

और फिर इस प्रकार डेकोरेशन डेकोरेटर का आयात करें:

from .utils import deprecated

@deprecated("Use method yyy instead")
def some_method()"
 pass

धन्यवाद, मैं इसका उपयोग कर रहा हूं उपयोगकर्ता को केवल डिप्रेसेशन संदेश दिखाने के बजाय सही जगह पर भेजने के लिए!
जर्मन अटानासियो

3
वास्तविक प्रश्न का उत्तर नहीं देता है।
कैटस्कुल

2

अद्यतन: मुझे लगता है कि बेहतर है, जब हम प्रत्येक कोड लाइन के लिए केवल पहली बार DeprecationWarning दिखाते हैं और जब हम अपना संदेश भेज सकते हैं:

import inspect
import traceback
import warnings
import functools

import time


def deprecated(message: str = ''):
    """
    This is a decorator which can be used to mark functions
    as deprecated. It will result in a warning being emitted
    when the function is used first time and filter is set for show DeprecationWarning.
    """
    def decorator_wrapper(func):
        @functools.wraps(func)
        def function_wrapper(*args, **kwargs):
            current_call_source = '|'.join(traceback.format_stack(inspect.currentframe()))
            if current_call_source not in function_wrapper.last_call_source:
                warnings.warn("Function {} is now deprecated! {}".format(func.__name__, message),
                              category=DeprecationWarning, stacklevel=2)
                function_wrapper.last_call_source.add(current_call_source)

            return func(*args, **kwargs)

        function_wrapper.last_call_source = set()

        return function_wrapper
    return decorator_wrapper


@deprecated('You must use my_func2!')
def my_func():
    time.sleep(.1)
    print('aaa')
    time.sleep(.1)


def my_func2():
    print('bbb')


warnings.simplefilter('always', DeprecationWarning)  # turn off filter
print('before cycle')
for i in range(5):
    my_func()
print('after cycle')
my_func()
my_func()
my_func()

परिणाम:

before cycle
C:/Users/adr-0/OneDrive/Projects/Python/test/unit1.py:45: DeprecationWarning: Function my_func is now deprecated! You must use my_func2!
aaa
aaa
aaa
aaa
aaa
after cycle
C:/Users/adr-0/OneDrive/Projects/Python/test/unit1.py:47: DeprecationWarning: Function my_func is now deprecated! You must use my_func2!
aaa
C:/Users/adr-0/OneDrive/Projects/Python/test/unit1.py:48: DeprecationWarning: Function my_func is now deprecated! You must use my_func2!
aaa
C:/Users/adr-0/OneDrive/Projects/Python/test/unit1.py:49: DeprecationWarning: Function my_func is now deprecated! You must use my_func2!
aaa

Process finished with exit code 0

हम केवल चेतावनी पथ पर क्लिक कर सकते हैं और PyCharm में लाइन पर जा सकते हैं।


2
वास्तविक प्रश्न का उत्तर नहीं देता है।
कैटस्कूल

0

स्टीवन वास्केलारो द्वारा इस उत्तर को संवर्धित करना :

यदि आप एनाकोंडा का उपयोग करते हैं, तो पहले deprecationपैकेज स्थापित करें :

conda install -c conda-forge deprecation 

फिर फ़ाइल के शीर्ष पर निम्नलिखित पेस्ट करें

import deprecation

@deprecation.deprecated(deprecated_in="1.0", removed_in="2.0",
                    current_version=__version__,
                    details="Use the bar function instead")
def foo():
    """Do some stuff"""
    return 1

पूर्ण प्रलेखन के लिए http://deprecation.readthedocs.io/ देखें ।


4
वास्तविक प्रश्न का उत्तर नहीं देता है।
कैटस्कूल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.