2008-10-03 11 views
23

मैं एक सजावट कैसे लिखूं जो वर्तमान कार्यशील निर्देशिका को पुनर्स्थापित करता है जो सजाए गए समारोह से पहले था? दूसरे शब्दों में, अगर मैं एक समारोह पर सजावट का उपयोग करता हूं जो os.chdir() करता है, तो फ़ंक्शन कहने के बाद cwd बदला नहीं जाएगा।पायथन - मैं एक सजावट कैसे लिखूं जो सीडब्ल्यूडी को पुनर्स्थापित करता है?

+1

और आपने सवाल पूछा और खुद को 3 मिनट में जवाब दिया क्योंकि ...? जाहिर है कि सवाल पूछने से पहले भी आपको जवाब था (जिसे शायद ही कभी सुधार किया जा सकता है)। मैं वास्तव में आपके तर्क को जानना चाहता हूं। – tzot

+6

एफएक्यू पूछताछ करता है "अपने प्रोग्रामिंग प्रश्न पूछने और जवाब देने के लिए भी बिल्कुल ठीक है"। इसमें प्रश्नों के लिए तीन आवश्यक मानदंड सूचीबद्ध हैं, और "आप उत्तर नहीं जानते हैं" उनमें से एक नहीं है। –

+2

मैंने कोड लिखा था और फिर यह निकला (रिफैक्टरिंग के बाद) कि मुझे इसकी आवश्यकता नहीं थी। मैंने सोचा कि स्टैक ओवरफ्लो इसे संग्रहीत करने के लिए एक अच्छी जगह है, और शायद अन्य लाभ उठा सकते हैं। –

उत्तर

13

path.py मॉड्यूल (जो तुम सच में अगर अजगर स्क्रिप्ट में रास्तों के साथ काम का उपयोग करना चाहिए) एक संदर्भ प्रबंधक है:

subdir = d/'subdir' #subdir is a path object, in the path.py module 
with subdir: 
    # here current dir is subdir 

#not anymore 

(क्रेडिट this blog post पर रोब से जाता है erto Alsina)

+1

यदि पथ.py अब अंतर्निहित है, तो शायद आपको http://stackoverflow.com/questions/3899761/will-the-real-path-py-please-stand-up का उत्तर देना चाहिए। –

+0

दुर्भाग्य से यह नहीं है, लेकिन धन्यवाद, मुझे – CharlesB

+0

प्रश्न से अवगत नहीं था, मुझे लगता है कि मैंने आपके उत्तर का गलत व्याख्या किया है। क्या आपका मतलब है कि संदर्भ प्रबंधक पथ.py में बनाया गया है? (मैंने सोचा था कि आपका मतलब है पथ पथ अब पाइथन में बनाया गया है।) –

3
def preserve_cwd(function): 
    def decorator(*args, **kwargs): 
     cwd = os.getcwd() 
     result = function(*args, **kwargs) 
     os.chdir(cwd) 
     return result 
    return decorator 

यहाँ उसके उपयोग के तरीके:

@preserve_cwd 
def test(): 
    print 'was:',os.getcwd() 
    os.chdir('/') 
    print 'now:',os.getcwd() 

>>> print os.getcwd() 
/Users/dspitzer 
>>> test() 
was: /Users/dspitzer 
now:/
>>> print os.getcwd() 
/Users/dspitzer 
+2

त्रुटि प्रबंधन की आवश्यकता है, मेरा जवाब देखें। – codeape

30

एक डेकोरेटर के लिए इस सवाल का जवाब दिया गया है; यह अनुरोध के अनुसार फ़ंक्शन परिभाषा चरण पर काम करता है।

अजगर 2.5+ के साथ

, आप भी ऐसा करने के लिए समारोह कॉल चरण में एक संदर्भ प्रबंधक का प्रयोग पर एक विकल्प है:

from __future__ import with_statement # needed for 2.5 ≤ Python < 2.6 
import contextlib, os 

@contextlib.contextmanager 
def remember_cwd(): 
    curdir= os.getcwd() 
    try: yield 
    finally: os.chdir(curdir) 

जो करता है, तो के रूप में समारोह कॉल समय की जरूरत के लिए इस्तेमाल किया जा सकता है:

print "getcwd before:", os.getcwd() 
with remember_cwd(): 
    walk_around_the_filesystem() 
print "getcwd after:", os.getcwd() 

यह एक अच्छा विकल्प है।

संपादित करें: मैंने कोडेप द्वारा सुझाए गए त्रुटि प्रबंधन को जोड़ा। चूंकि मेरा जवाब चुना गया है, इसलिए एक पूर्ण उत्तर, अन्य सभी मुद्दों को अलग करना उचित है।

+0

* और * इसका उपयोग उपरोक्त सजावटी लिखने के लिए किया जा सकता है :) – Constantin

+1

त्रुटि प्रबंधन की आवश्यकता है, मेरा उत्तर देखें। – codeape

+0

क्या त्रुटि प्रबंधन को स्पष्ट प्रयास/अंत में आवश्यकता है? मैंने सोचा कि संदर्भ प्रबंधकों का मुद्दा यह था कि प्रबंधक .__ exit__ हमेशा कहा जाता था। लेकिन फिर, मैंने कभी भी सजावटी से सजावटी की कोशिश नहीं की है, इसलिए मुझे नहीं पता कि समस्याएं क्या हैं। –

17

दिए गए उत्तरों को ध्यान में रखना विफल रहता है कि लपेटा हुआ कार्य अपवाद बढ़ा सकता है। उस स्थिति में, निर्देशिका को कभी भी बहाल नहीं किया जाएगा। नीचे दिया गया कोड पिछले उत्तरों में अपवाद हैंडलिंग जोड़ता है।

एक डेकोरेटर के रूप में:

def preserve_cwd(function): 
    @functools.wraps(function) 
    def decorator(*args, **kwargs): 
     cwd = os.getcwd() 
     try: 
      return function(*args, **kwargs) 
     finally: 
      os.chdir(cwd) 
    return decorator 

और एक संदर्भ प्रबंधक के रूप में:

@contextlib.contextmanager 
def remember_cwd(): 
    curdir = os.getcwd() 
    try: 
     yield 
    finally: 
     os.chdir(curdir) 
संबंधित मुद्दे