दिलचस्प पोस्ट
ऑपरेटर क्या करता है? सरणियों पर NSUserDefaults का उपयोग करना एक हैंडलबार 'प्रत्येक' लूप के साथ अभिभावकों के एक्सेस गुण यह निर्धारित करने के लिए कि क्या दशमलव / डबल पूर्णांक है? गिट में सबसे बदली हुई फाइलों को ढूंढना डिबगिंग के लिए विजुअल स्टूडियो वेब। कॉन्फिग ट्रांस्फ़ॉर्म का उपयोग करें PHP के साथ आरएसएस / एटम फीड्स को पार्स करने का सबसे अच्छा तरीका आईडी ({}) == आईडी ({}) और आईडी () == आईडी () CPython में क्यों है? जावा में सूची बनाम मानचित्र जावा में सूची के लिए मानचित्र को कैसे रूपांतरित करना है? एनजी-दोहराने, एनजी-शो (कोणीय) का उपयोग करके गतिशील रूप से निर्मित इनपुटों को कैसे मान्य किया जाए वेबसाइटों पर सूचना ध्वनि कैसे खेलें? मॉडलिंग पॉलीमोर्फ़िक एसोसिएशन डेटाबेस-पहले बनाम कोड-पहले मूल एक्सेस प्रमाणीकरण के साथ जेसूप कनेक्शन जेएनडीआई डाटास्रस के माध्यम से डेटाबेस से कनेक्ट करने के लिए हाइबरनेट कॉन्फ़िगर करें

अजगर: प्रोग्राम का एकल उदाहरण

क्या कोई प्रोग्राम चलाने का केवल एक उदाहरण है एक पायथनिक तरीका है?

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

(ध्यान दें कि कार्यक्रम को कभी-कभी असफल होने की उम्मीद है, अर्थात सेगफ़ॉल्ट- तो "लॉक फाइल" जैसी चीज़ें काम नहीं करेंगी)

अद्यतन : प्रस्तावित समाधानों को अधिक जटिल और केवल एक गैर-मौजूद सर्वर के साथ कब्जा कर लिया गया पोर्ट होने से कम निर्भर है, इसलिए मुझे उस एक के साथ जाना होगा।

Solutions Collecting From Web of "अजगर: प्रोग्राम का एकल उदाहरण"

निम्नलिखित कोड को काम करना चाहिए, यह क्रॉस-प्लेटफॉर्म है और पायथन 2.4-3.2 पर चलता है। मैंने इसे विंडोज, ओएस एक्स और लिनक्स पर परीक्षण किया।

from tendo import singleton me = singleton.SingleInstance() # will sys.exit(-1) if other instance is running 

नवीनतम कोड संस्करण उपलब्ध है singleton.py कृपया यहां कीड़े दर्ज करें

आप निम्न विधियों में से किसी एक का उपयोग कर स्थापित कर सकते हैं:

सरल, क्रॉस-प्लेटफॉर्म समाधान, ज़गोदा द्वारा एक अन्य प्रश्न में पाया गया:

 import fcntl, sys pid_file = 'program.pid' fp = open(pid_file, 'w') try: fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: # another instance is running sys.exit(0) 

एस लोट के सुझाव की तरह बहुत कुछ है, लेकिन कोड के साथ।

यह कोड लिनक्स विशिष्ट है (यह 'अमूर्त' यूनिक्स डोमेन सॉकेट्स का उपयोग करता है), लेकिन यह सरल है और बागी ताला फ़ाइलों को लगभग नहीं छोड़ेगा। मैं इसे उपरोक्त समाधान के लिए पसंद करता हूं क्योंकि उसे विशेष रूप से आरक्षित टीसीपी पोर्ट की आवश्यकता नहीं होती है

 try: import socket s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) ## Create an abstract socket, by prefixing it with null. s.bind( '\0postconnect_gateway_notify_lock') except socket.error as e: error_code = e.args[0] error_string = e.args[1] print "Process already running (%d:%s ). Exiting" % ( error_code, error_string) sys.exit (0) 

अनन्य स्ट्रिंग postconnect_gateway_notify_lock को एक से अधिक प्रोग्राम्स को अनुमति देने के लिए बदला जा सकता है जिसके लिए एक एकल आवृत्ति की आवश्यकता होती है।

मुझे नहीं पता कि यह अजगर पर्याप्त है, लेकिन जावा में एक परिभाषित बंदरगाह पर सुनना एक बहुत व्यापक रूप से इस्तेमाल किया समाधान है, क्योंकि यह सभी प्रमुख प्लेटफार्मों पर काम करता है और प्रोग्राम को क्रैश करने में कोई समस्या नहीं है।

बंदरगाह को सुनने का एक अन्य लाभ यह है कि आप चल रहे उदाहरण के लिए एक कमांड भेज सकते हैं। उदाहरण के लिए जब उपयोगकर्ता कार्यक्रम को दूसरी बार शुरू करते हैं, तो आप चल रहे उदाहरण को एक अन्य विंडो खोलने के लिए कहने के लिए एक कमांड भेज सकते हैं (उदाहरण के लिए फ़ायरफ़ॉक्स क्या है, उदाहरण के लिए। मुझे नहीं पता कि क्या वे टीसीपी पोर्ट या नामित पाइप का उपयोग करते हैं या कुछ ऐसा है, 'हालांकि)।

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

 import os import sys import fcntl fh=0 def run_once(): global fh fh=open(os.path.realpath(__file__),'r') try: fcntl.flock(fh,fcntl.LOCK_EX|fcntl.LOCK_NB) except: os._exit(0) run_once() 

एक अन्य मुद्दे (http://stackoverflow.com/questions/2959474) में पोस्ट करने के बाद स्लाव-एन का सुझाव मिला। यह एक को एक समारोह के रूप में कहा जाता है, निष्पादित स्क्रिप्ट फ़ाइल को लॉक करता है (एक पीआईडी ​​फ़ाइल नहीं) और जब तक स्क्रिप्ट समाप्त नहीं होती (सामान्य या त्रुटि) लॉक रखता है।

एक pid फ़ाइल का उपयोग करें आपके पास कुछ ज्ञात स्थान है, "/ path / to / pidfile" और स्टार्टअप पर आप ऐसा कुछ करते हैं (आंशिक रूप से स्यूडोकोड क्योंकि मैं प्री-कॉफी हूँ और सभी कठिन काम करना नहीं चाहते हैं):

 import os, os.path pidfilePath = """/path/to/pidfile""" if os.path.exists(pidfilePath): pidfile = open(pidfilePath,"r") pidString = pidfile.read() if <pidString is equal to os.getpid()>: # something is real weird Sys.exit(BADCODE) else: <use ps or pidof to see if the process with pid pidString is still running> if <process with pid == 'pidString' is still running>: Sys.exit(ALREADAYRUNNING) else: # the previous server must have crashed <log server had crashed> <reopen pidfilePath for writing> pidfile.write(os.getpid()) else: <open pidfilePath for writing> pidfile.write(os.getpid()) 

इसलिए, दूसरे शब्दों में, आप जाँच रहे हैं कि क्या एक pidfile मौजूद है; यदि नहीं, तो उस फ़ाइल को अपना पिन लिखें। यदि pidfile मौजूद है, तो यह देखने के लिए जांचें कि क्या pid चलने की प्रक्रिया का pid है; यदि हां, तो आपको एक और लाइव प्रक्रिया चल रही है, इसलिए बस बंद करें यदि नहीं, तो पिछली प्रक्रिया दुर्घटनाग्रस्त हो गई है, तो लॉग इन करें, और फिर अपने स्वयं के pid को फाइल में पुराने के स्थान पर लिखें। फिर जारी रखें

आप पहले से ही इसी तरह के प्रश्न का एक और धागा में उत्तर प्राप्त कर चुके हैं, इसलिए पूर्णता के लिए यह देखने के लिए कि विंडोज यूनिंग नामक म्यूट एक्स पर इसे कैसे हासिल किया जाए।

http://code.activestate.com/recipes/474070/

यह काम कर सकता है

  1. किसी ज्ञात स्थान पर एक PID फ़ाइल बनाने का प्रयास करें अगर आप असफल हो जाते हैं, तो किसी ने फ़ाइल को लॉक किया है, आप कर चुके हैं

  2. जब आप सामान्य रूप से समाप्त करते हैं, पीआईडी ​​फ़ाइल को बंद करें और निकालें, तो किसी और को इसे अधिलेखित कर सकते हैं

आप अपने प्रोग्राम को शेल स्क्रिप्ट में लपेट कर सकते हैं जो पीआईडी ​​फ़ाइल को निकाल देता है भले ही आपका प्रोग्राम क्रैश हो।

यदि आप इसे लटकाते हैं, तो आप प्रोग्राम को मारने के लिए पीआईडी ​​फ़ाइल का उपयोग भी कर सकते हैं।

लॉक-फाईल का इस्तेमाल करना यूनिक्स पर काफी सामान्य तरीका है। यदि यह क्रैश हो जाता है, तो आपको मैन्युअल रूप से साफ करना होगा आप फ़ाइल में पीआईडी ​​को स्टोर कर सकते हैं, और स्टार्टअप पर जांच कर सकते हैं कि क्या इस पीआईडी ​​के साथ कोई प्रक्रिया है, तो लॉक-फाइल को ओवरराइड करते हुए नहीं। (हालांकि, आपको पढ़ने-फ़ाइल-चेक-पीआईडी-पुनर्लेखन फ़ाइल के आसपास लॉक की भी आवश्यकता है) आप पाएंगे कि आपको ओएस- पैकेज में पीआईडी ​​प्राप्त करने और जांचने के लिए क्या चाहिए। अगर किसी दिए गए पीआईड के साथ एक प्रक्रिया मौजूद है, तो यह जांचने का एक सामान्य तरीका है कि उसे एक गैर-घातक संकेत भेजना है।

अन्य विकल्प झुंड या पॉज़िक्स सैकॉफोर के साथ संयोजन कर सकते हैं।

एक नेटवर्क सॉकेट खोलना, जैसा कि सौया प्रस्तावित है, संभवतः सबसे आसान और सबसे पोर्टेबल होगा।

अपने आवेदन के लिए wxPython का उपयोग करने वाले किसी भी व्यक्ति के लिए, आप यहां wx.SingleInstanceChecker फ़ंक्शन का उपयोग कर सकते हैं ।

मैं व्यक्तिगत रूप से wx.App एक उपवर्ग का उपयोग करता wx.App जो कि wx.App उपयोग करता है और wx.SingleInstanceChecker OnInit() से False लौटाता है यदि इस तरह के अनुप्रयोग को पहले से ही निष्पादित करने वाला एक मौजूदा उदाहरण है:

 import wx class SingleApp(wx.App): """ class that extends wx.App and only permits a single running instance. """ def OnInit(self): """ wx.App init function that returns False if the app is already running. """ self.name = "SingleApp-%s".format(wx.GetUserId()) self.instance = wx.SingleInstanceChecker(self.name) if self.instance.IsAnotherRunning(): wx.MessageBox( "An instance of the application is already running", "Error", wx.OK | wx.ICON_WARNING ) return False return True 

यह एक सरल ड्रॉप-इन विकल्प है जो कई उदाहरणों को प्रतिबंधित करता है। इसका उपयोग करने के लिए बस अपने SingleApp में wx.App साथ SingleApp को प्रतिस्थापित करें जैसे:

 app = SingleApp(redirect=False) frame = wx.Frame(None, wx.ID_ANY, "Hello World") frame.Show(True) app.MainLoop() 

मैं इसे एक उत्तर के रूप में पोस्ट कर रहा हूं क्योंकि मैं एक नया उपयोगकर्ता हूं और स्टैक ओवरफ़्लो मुझे अभी तक मतदान नहीं करने देगा।

Sorin Sbarnea के समाधान ओएस एक्स, लिनक्स और विंडोज के तहत मेरे लिए काम करता है, और मैं इसके लिए आभारी हूं।

हालांकि, tempfile.gettempdir () OS X और Windows के तहत एक और कुछ अन्य / कुछ / सभी /? (?) * निक्से (इस तथ्य की अनदेखी कर रहा है कि OS X भी यूनिक्स!) के तहत एक तरह से व्यवहार करता है। अंतर इस कोड के लिए महत्वपूर्ण है।

ओएस एक्स और विंडोज में उपयोगकर्ता-विशिष्ट टेम्पकों की निर्देशिकाएं हैं, इसलिए एक उपयोगकर्ता द्वारा बनाई गई एक टेम्पफ़ाइल दूसरे उपयोगकर्ता के लिए दृश्यमान नहीं है। इसके विपरीत, * निक के कई संस्करणों के तहत (मैं उबंटु 9, आरएचईएल 5, ओपनसोलारिस 2008 और फ्रीबीएसडी 8 का परीक्षण किया), सभी उपयोगकर्ताओं के लिए टेम्पप डायर / टीएमपी है

इसका मतलब है कि जब एक बहु-उपयोगकर्ता मशीन पर लॉकफ़ाइल बनाई जाती है, तो इसे / tmp में बनाया गया है और केवल उपयोगकर्ता जो लॉकफाइल बनाता है पहली बार अनुप्रयोग को चलाने में सक्षम हो जाएगा।

एक संभावित समाधान ताला फ़ाइल के नाम पर मौजूदा उपयोगकर्ता नाम को एम्बेड करना है।

यह ध्यान देने योग्य है कि ओपी के पोर्ट को हथियाने का समाधान भी बहु-उपयोगकर्ता मशीन पर दुर्व्यवहार करेगा।

मैं अपने सज्जन पर single_process उपयोग करता हूं;

 pip install single_process 

उदाहरण :

 from single_process import single_process @single_process def main(): print 1 if __name__ == "__main__": main() 

देखें: https://pypi.python.org/pypi/single_process/1.0

लिनक्स उदाहरण

यह विधि आपके पास आवेदन बंद करने के बाद स्वचालित रूप से हटाई गई एक अस्थायी फ़ाइल के निर्माण पर आधारित है। कार्यक्रम की शुरूआत हम फ़ाइल के अस्तित्व की पुष्टि करते हैं; अगर फ़ाइल मौजूद है (लंबित निष्पादन है), कार्यक्रम बंद है; अन्यथा यह फ़ाइल बनाता है और कार्यक्रम के निष्पादन को जारी रखता है।

 from tempfile import * import time import os import sys f = NamedTemporaryFile( prefix='lock01_', delete=True) if not [f for f in os.listdir('/tmp') if f.find('lock01_')!=-1] else sys.exit() YOUR CODE COMES HERE 

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

स्टार्टअप पर, आपकी प्रक्रिया किसी विशेष समूह में सभी प्रक्रियाओं को 'kill -0' भेजती है। यदि ऐसी कोई प्रक्रिया मौजूद है, तो यह बाहर निकलता है। तो यह समूह में जुड़ जाता है कोई अन्य प्रक्रिया उस समूह का उपयोग नहीं करती है

हालांकि, इसमें एक दौड़ की स्थिति है – कई प्रक्रियाएं ठीक उसी समय पूरी कर सकती हैं और सभी समूह में शामिल होकर और एक साथ चल रहे हैं। जब तक आप किसी प्रकार के म्यूटिक्स को जोड़कर जोड़ते हैं, तब तक आपको प्रक्रिया समूह की आवश्यकता नहीं होती है।

यह स्वीकार्य हो सकता है अगर आपकी प्रक्रिया केवल क्रोन द्वारा शुरू हो जाती है, एक बार हर मिनट या हर घंटे, लेकिन यह मुझे थोड़ा परेशान करता है कि यह उस दिन ठीक से गलत होगा जब आप इसे नहीं चाहते हैं

मुझे लगता है कि यह सब के बाद एक बहुत अच्छा समाधान नहीं है, जब तक कि कोई इस पर सुधार न करे?

मैं पिछले हफ्ते इस सटीक समस्या में गया था, और हालांकि मुझे कुछ अच्छे समाधान मिल गए, मैंने एक बहुत ही सरल और स्वच्छ अजगर पैकेज बनाने का निर्णय लिया और इसे पीईपीआई पर अपलोड किया। यह tendo से भिन्न होता है क्योंकि यह किसी स्ट्रिंग संसाधन नाम को लॉक कर सकता है। यद्यपि आप निश्चित रूप से एक ही प्रभाव को प्राप्त करने के लिए __file__ लॉक कर सकते हैं।

इसके साथ स्थापित करें: pip install quicklock

इसका प्रयोग करना अत्यंत सरल है:

 [nate@Nates-MacBook-Pro-3 ~/live] python Python 2.7.6 (default, Sep 9 2014, 15:04:36) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from quicklock import singleton >>> # Let's create a lock so that only one instance of a script will run ... >>> singleton('hello world') >>> >>> # Let's try to do that again, this should fail ... >>> singleton('hello world') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/nate/live/gallery/env/lib/python2.7/site-packages/quicklock/quicklock.py", line 47, in singleton raise RuntimeError('Resource <{}> is currently locked by <Process {}: "{}">'.format(resource, other_process.pid, other_process.name())) RuntimeError: Resource <hello world> is currently locked by <Process 24801: "python"> >>> >>> # But if we quit this process, we release the lock automatically ... >>> ^D [nate@Nates-MacBook-Pro-3 ~/live] python Python 2.7.6 (default, Sep 9 2014, 15:04:36) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from quicklock import singleton >>> singleton('hello world') >>> >>> # No exception was thrown, we own 'hello world'! 

एक नज़र डालें: https://pypi.pythth.org/pypi/quicklock

यहां मेरा अंतिम Windows-only समाधान है निम्नलिखित को एक मॉड्यूल में रखें, जिसे शायद 'onlyone.py' कहा जाता है, या जो भी हो उस मॉड्यूल को सीधे अपने __ मुख्य __ पाइथन स्क्रिप्ट फ़ाइल में शामिल करें।

 import win32event, win32api, winerror, time, sys, os main_path = os.path.abspath(sys.modules['__main__'].__file__).replace("\\", "/") first = True while True: mutex = win32event.CreateMutex(None, False, main_path + "_{<paste YOUR GUID HERE>}") if win32api.GetLastError() == 0: break win32api.CloseHandle(mutex) if first: print "Another instance of %s running, please wait for completion" % main_path first = False time.sleep(1) 

व्याख्या

कोड स्क्रिप्ट के पूर्ण पथ से प्राप्त नाम के साथ एक म्यूटक्स बनाने का प्रयास करता है वास्तविक फ़ाइल सिस्टम के साथ संभावित भ्रम से बचने के लिए हम आगे-स्लैश का उपयोग करते हैं।

लाभ

  • कोई कॉन्फ़िगरेशन या 'जादू' पहचानकर्ता की जरूरत नहीं है, इसकी आवश्यकता के अनुसार कई अलग-अलग लिपियों में इसका उपयोग करें।
  • कोई बासी फ़ाइलों को नहीं छोड़ दिया जाता है, म्यूट एक्स आपके साथ मर जाता है
  • प्रतीक्षा करते समय सहायक संदेश प्रिंट करता है

मैं बस ऐसा कुछ करता हूं:

 if commands.getstatusoutput("mkdir /tmp/test")[0]: print "Exiting" sys.exit(1) 

और कहीं मेरे कोड के अंत में, मैं निर्देशिका को निकाल दूँगा mkdir एक परमाणु है और यहां बहुत अच्छी तरह से काम करता है।