নিশ্চিত হয়ে নিন যে কোনও প্রোগ্রামের একক উদাহরণ চলমান আছে


120

কোনও প্রোগ্রাম চালু থাকার জন্য কি পাইথোনিক উপায় রয়েছে?

আমি যে যুক্তিসঙ্গত সমাধানটি নিয়ে এসেছি তা হ'ল এটি কোনও পোর্টের সার্ভার হিসাবে চালানোর চেষ্টা করা হচ্ছে, তারপরে দ্বিতীয় প্রোগ্রামটি একই বন্দরে আবদ্ধ হওয়ার চেষ্টা করছে - ব্যর্থ হয়। তবে এটি সত্যিই দুর্দান্ত ধারণা নয়, সম্ভবত এর চেয়ে আরও হালকা কিছু আছে?

(বিবেচনায় রাখুন যে প্রোগ্রামটি কখনও কখনও ব্যর্থ হয়ে যায়, যেমন সেগফোল্ট - সুতরাং "লক ফাইল" এর মতো জিনিসগুলি কাজ করবে না)


1
আপনি যদি সেগফল্টকে সন্ধান এবং ঠিক করে থাকেন তবে সম্ভবত আপনার জীবন আরও সহজ হবে। এটি করা সহজ কাজ নয়।
ডেভিড লক

এটি আমার লাইব্রেরিতে নেই, এটি অজগরটির লিবএক্সএমএল বাইন্ডিংগুলিতে এবং অত্যন্ত লাজুক - দু'দিনের মধ্যে কেবল একবার আগুন লাগে।
স্লাভা ভি

5
পাইথনের স্ট্যান্ডার্ড লাইব্রেরি ফ্লককে সমর্থন করে () যা আধুনিক ইউনিক্স প্রোগ্রামের জন্য ডান থিং। পোর্ট খোলার ফলে অনেক বেশি সীমাবদ্ধ নেমস্পেসের স্পট ব্যবহার করা হয়, অন্যদিকে পিডফায়ালগুলি আরও জটিল কারণ এগুলি নিরাপদে অবৈধ করতে আপনার চলমান প্রক্রিয়াগুলি পরীক্ষা করা দরকার; পালের কোনও সমস্যা নেই।
চার্লস ডাফি

এস / ইউনিক্স / লিনাক্স / সেখানে আপনি যান, এফটিএফওয়াই।
ক্যালিসিন

উত্তর:


100

নিম্নলিখিত কোডটি কাজটি করা উচিত, এটি ক্রস প্ল্যাটফর্ম এবং পাইথন ২.৪-৩.২ এ চলে runs আমি এটি উইন্ডোজ, ওএস এক্স এবং লিনাক্সে পরীক্ষা করেছি।

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

সর্বশেষতম কোড সংস্করণটি সিঙ্গলটন.পিপি উপলব্ধ । দয়া করে এখানে বাগ ফাইল করুন

আপনি নিম্নলিখিত পদ্ধতিগুলির একটি ব্যবহার করে টেন্ড ইনস্টল করতে পারেন:


2
আমি উত্তর আপডেট করেছি এবং সর্বশেষ সংস্করণে একটি লিঙ্ক অন্তর্ভুক্ত করেছি। যদি আপনি কোনও বাগ খুঁজে পান তবে দয়া করে এটি গিথুবে জমা দিন এবং আমি যত তাড়াতাড়ি সম্ভব এটি সমাধান করব।
সোমিন

2
@Johny_M ধন্যবাদ, আমি একটি প্যাচ এবং মুক্তি একটি নতুন সংস্করণ তৈরি pypi.python.org/pypi/tendo
sorin

2
পাইথন ২.6 এর অধীনে উইন্ডোতে এই বাক্য গঠন আমার পক্ষে কাজ করে না। আমার জন্য যা কাজ করেছে তা হল: 1: টেন্ডো আমদানি সিঙ্গলটন 2: me = সিঙ্গলটন.সিংলইনস্ট্যান্স ()
ব্রায়ান

25
এই হিসাবে তুচ্ছ কিছু জন্য অন্য নির্ভরতা? খুব আকর্ষণীয় লাগে না।
নটহাগো

2
সিঙ্গলটন কি সিগটার্ম পায় এমন প্রক্রিয়াগুলি হ্যান্ডেল করে (উদাহরণস্বরূপ যদি কোনও প্রক্রিয়া খুব দীর্ঘকাল চলতে থাকে), অথবা আমাকে কী তা হ্যান্ডেল করতে হবে?
জিমজেটি

43

সহজ, ক্রস প্ল্যাটফর্ম সমাধান, zgoda দ্বারা অন্য প্রশ্নের মধ্যে পাওয়া গেছে :

import fcntl
import os
import sys

def instance_already_running(label="default"):
    """
    Detect if an an instance with the label is already running, globally
    at the operating system level.

    Using `os.open` ensures that the file pointer won't be closed
    by Python's garbage collector after the function's scope is exited.

    The lock will be released when the program exits, or could be
    released if the file pointer were closed.
    """

    lock_file_pointer = os.open(f"/tmp/instance_{label}.lock", os.O_WRONLY)

    try:
        fcntl.lockf(lock_file_pointer, fcntl.LOCK_EX | fcntl.LOCK_NB)
        already_running = False
    except IOError:
        already_running = True

    return already_running

অনেকটা এস.লোটের পরামর্শ মতো তবে কোড সহ with


কৌতূহলের বাইরে: এটি কি সত্যিই ক্রস প্ল্যাটফর্ম? এটি কি উইন্ডোজে কাজ করে?
জোছিম সউর

1
fcntlউইন্ডোজে কোনও মডিউল নেই (যদিও কার্যকারিতাটি অনুকরণ করা যেতে পারে)।
jfs

10
টিপ: আপনি যদি এটিকে কোনও ফাংশনে আবদ্ধ করতে চান তবে 'fp' অবশ্যই গ্লোবাল হতে হবে বা ফাংশনটি প্রস্থান করার পরে ফাইলটি বন্ধ হয়ে যাবে।
সেমিচিনজিটি

1
@ মিরকো কন্ট্রোল + জেড কোনও অ্যাপ্লিকেশন থেকে বের হয় না (যে কোনও ওএসের বিষয়ে আমি সচেতন), এটি এটি স্থগিত করে। অ্যাপ্লিকেশনটি সাথে অগ্রভাগে ফিরে যেতে পারে fg। সুতরাং, মনে হচ্ছে এটি আপনার জন্য সঠিকভাবে কাজ করছে (যেমন অ্যাপ্লিকেশনটি এখনও সক্রিয়, তবে স্থগিত করা হয়েছে, তাই লকটি স্থানে রয়েছে)।
স্যাম বুল

1
আমার পরিস্থিতিতে এই কোডটির (লিনাক্সে পাইথন ৩.৮.৩) মোডিফিকেশন প্রয়োজন:lock_file_pointer = os.open(lock_path, os.O_WRONLY | os.O_CREAT)
বাজিওরেক

30

এই কোডটি লিনাক্স নির্দিষ্ট। এটি 'অ্যাবস্ট্রাক্ট' ইউনিক্স ডোমেন সকেট ব্যবহার করে তবে এটি সহজ এবং বাসি লক ফাইলগুলি আর ছাড়বে না। আমি এটি উপরের সমাধানটিকে পছন্দ করি কারণ এর জন্য বিশেষভাবে সংরক্ষিত টিসিপি পোর্টের প্রয়োজন হয় না।

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একক দাবী প্রয়োগ করা প্রয়োজন এমন একাধিক প্রোগ্রামকে মঞ্জুরি দেওয়ার জন্য অনন্য স্ট্রিংটি পরিবর্তন করা যেতে পারে।


1
রবার্তো, আপনি কি নিশ্চিত যে কার্নেল প্যানিক বা হার্ড রিসেটের পরে, ফাইল p 0 পোষ্টকনেক্ট_গেটও_নোটাইফ_লক বুট আপ এ উপস্থিত হবে না? আমার ক্ষেত্রে AF_UNIX সকেট ফাইল এটির পরে এখনও উপস্থিত এবং এটি পুরো ধারণাটিকে নষ্ট করে। সুনির্দিষ্ট ফাইল নেমে লক অর্জনের সাথে উপরের সমাধানটি এক্ষেত্রে অনেক নির্ভরযোগ্য।
ড্যানিয়েলো গুরিয়ানভ

2
হিসাবে উপরে উল্লেখ করেছি, এই সমাধান লিনাক্স কিন্তু কাজ করে না ম্যাক OS X উপর
বিলাল এবং ওলগা

2
এই সমাধান কাজ করে না। আমি এটি উবুন্টু 14.04 এ চেষ্টা করেছি। একই স্ক্রিপ্টটি একই সাথে 2 টি টার্মিনাল উইন্ডো থেকে চালান। তারা দু'জন ঠিকঠাক চালায়।
ডিমন

1
এটি উবুন্টু 16 এ আমার পক্ষে কাজ করেছিল And ডিমন আমি মনে করি আপনি নিজের পরীক্ষায় কিছু ভুল করেছেন। (সম্ভবত আপনি উপরের কোড দৌড়ে পালিয়ে যান আপনার স্ক্রিপ্টটি ঘুম করতে, তাই এটি অবিলম্বে বন্ধ করেছে এবং সকেট মুক্তি ভুলে গেছি।)
লুক

1
এটা ঘুমের প্রশ্ন নয়। কোডটি কেবল ইনলাইন কোড হিসাবে কাজ করে। আমি এটি একটি ফাংশনে রাখছি। ফাংশনটি উপস্থিত হওয়ার সাথে সাথে সকেটটি অদৃশ্য হয়ে গেল।
স্টিভ কোহেন

25

আমি জানি না এটি যথেষ্ট অজগর কিনা, তবে জাভা বিশ্বে কোনও সংজ্ঞায়িত বন্দরে শোনা একটি বেশ ব্যাপকভাবে ব্যবহৃত সমাধান, কারণ এটি সমস্ত বড় প্ল্যাটফর্মগুলিতে কাজ করে এবং ক্র্যাশিং প্রোগ্রামগুলির সাথে কোনও সমস্যা নেই।

একটি বন্দর শোনার আরেকটি সুবিধা হ'ল আপনি চলমান দৃষ্টান্তে একটি আদেশ পাঠাতে পারেন। উদাহরণস্বরূপ যখন ব্যবহারকারীগণ দ্বিতীয়বার প্রোগ্রামটি শুরু করেন, আপনি চলমান উদাহরণটি অন্য উইন্ডোটি খুলতে বলার জন্য একটি আদেশ পাঠাতে পারেন (উদাহরণস্বরূপ, ফায়ারফক্স এটি করে। আমি জানি না তারা টিসিপি পোর্ট বা নামযুক্ত পাইপ ব্যবহার করে কিনা বা 'যদিও' এর মতো কিছু।


+1 করুন করার জন্য, বিশেষ যেহেতু এটি আমাকে চলমান উদাহরণস্বরূপ অবহিত করার, তাই এটি অন্য একটি উইন্ডোতে সৃষ্টি, ইত্যাদি অনুমতি দেয়, পপ আপ
WhyNotHugo

1
যেমন ব্যবহার করুন import socket; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.bind(('localhost', DEFINED_PORT))। একটি OSErrorযদি অন্য প্রক্রিয়া একই বন্দর আবদ্ধ হয় উত্থাপিত করা হবে না।
crishoj

12

এর আগে অজগর কখনও লেখা হয়নি, তবে এটি দু'একটি বা আরও বেশি সংকোচনের মাধ্যমে শুরু হওয়া রোধ করার জন্য আমি সবেমাত্র mycheckPoint এ প্রয়োগ করেছি:

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)। এটিকে ফাংশন হিসাবে ডাকা হয়, এক্সিকিউটিভ স্ক্রিপ্ট ফাইলটি (পিড ফাইল নয়) লক করে এবং স্ক্রিপ্ট শেষ না হওয়া অবধি লকটি বজায় রাখে (স্বাভাবিক বা ত্রুটি)।


খুবই ভদ্র. আমি এটি পরিবর্তন করেছি যাতে এটি স্ক্রিপ্টের যুক্তিগুলির থেকে পথ পায়। এটিকে সাধারণ কোথাও এম্বেড
করারও পরামর্শ দেয়

10

একটি পিড ফাইল ব্যবহার করুন। আপনার কিছু পরিচিত অবস্থান রয়েছে, "/ পাথ / টু / পিডফিল" এবং প্রারম্ভের সময় আপনি এই জাতীয় কিছু করেন (আংশিক সিউডোকোড কারণ আমি প্রাক কফি এবং এত কঠিন কাজ করতে চাই না):

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())

সুতরাং, অন্য কথায়, আপনি একটি পিডফিল বিদ্যমান কিনা তা পরীক্ষা করছেন; যদি তা না হয় তবে সেই ফাইলটিতে আপনার পিড লিখুন। যদি পিডফাইলটি বিদ্যমান থাকে, তবে পিডটি চলমান প্রক্রিয়ার পিড কিনা তা পরীক্ষা করে দেখুন; যদি তা হয় তবে আপনার আর একটি লাইভ প্রক্রিয়া চলমান আছে, তাই কেবল বন্ধ করুন। যদি তা না হয়, তবে পূর্ববর্তী প্রক্রিয়াটি ক্র্যাশ হয়ে গেছে, তাই এটি লগ করুন এবং তারপরে পুরানোটির জায়গায় ফাইলটিতে নিজের পিড লিখুন। তারপরে চালিয়ে যান।


4
এটির একটি রেসের শর্ত রয়েছে। পরীক্ষার পরে লেখার ক্রম দুটি প্রোগ্রামের ব্যতিক্রম প্রায় একই সাথে শুরু হতে পারে, কোনও ফাইল খুঁজে পাবে না এবং একই সাথে লেখার জন্য খোলার চেষ্টা করবে। এটা তোলে উচিত এক একটি ব্যতিক্রম বাড়াতে, অন্যান্য এগিয়ে যেতে অনুমতি দেয়।
এস.লোট

6

আপনি ইতিমধ্যে অন্য থ্রেডে অনুরূপ প্রশ্নের উত্তর খুঁজে পেয়েছেন, সুতরাং সম্পূর্ণতার জন্য কীভাবে উইন্ডোজ আনিং নামক মুটেক্সে এটি অর্জন করা যায় তা দেখুন।

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


5

এটি কাজ করতে পারে।

  1. একটি পরিচিত স্থানে একটি পিআইডি ফাইল তৈরি করার চেষ্টা করুন। যদি আপনি ব্যর্থ হন তবে কারও কাছে ফাইলটি লক হয়ে গেছে, আপনি কাজ শেষ করেছেন।

  2. আপনি যখন সাধারণভাবে শেষ করেন, পিআইডি ফাইলটি বন্ধ করুন এবং সরান, যাতে অন্য কেউ এটি ওভাররাইট করতে পারে।

আপনি আপনার প্রোগ্রামটি শেল স্ক্রিপ্টে মোড়াতে পারেন যা আপনার প্রোগ্রামটি ক্র্যাশ হয়ে গেলেও পিআইডি ফাইল সরিয়ে দেয়।

প্রোগ্রামটি হ্যাং হয়ে থাকলে আপনি মারতে পিআইডি ফাইলটিও ব্যবহার করতে পারেন।


3

লক-ফাইল ব্যবহার করা ইউনিক্সে বেশ সাধারণ পদ্ধতি। যদি এটি ক্রাশ হয়, আপনাকে ম্যানুয়ালি পরিষ্কার করতে হবে। আপনি ফাইলটিতে পিআইডি স্টোর করতে পারেন এবং এই পিআইডি দিয়ে কোনও প্রক্রিয়া আছে কিনা তা শুরুতে পরীক্ষা করে দেখুন, যদি না হয় তবে লক-ফাইলকে ওভাররাইড করে। (তবে, আপনাকে পঠন-ফাইল-চেক-পিড-পুনর্লিখন-ফাইলের চারপাশে একটি লক প্রয়োজন)। আপনি পেয়ে এবং PID চেক করার জন্য যা প্রয়োজন পাবেন অপারেটিং সিস্টেম প্যাকেজে পিড যাবেন। প্রদত্ত পিড সহ কোনও প্রক্রিয়া আছে কিনা তা যাচাইয়ের সাধারণ উপায় হ'ল এটি একটি অ-মারাত্মক সংকেত প্রেরণ করা।

অন্যান্য বিকল্পগুলি এটি পর্ব বা পিক্সিক্স সেমোফোরগুলির সাথে একত্রিত হতে পারে।

স্যুয়ার প্রস্তাবিত একটি নেটওয়ার্ক সকেট খোলার বিষয়টি সম্ভবত সবচেয়ে সহজ এবং বহনযোগ্য।


3

যে কেউ তাদের অ্যাপ্লিকেশনটির জন্য ডাব্লুএক্সপিথন ব্যবহার করছেন , আপনি wx.SingleInstanceChecker এখানে ডকুমেন্টেড ফাংশনটি ব্যবহার করতে পারেন ।

আমি ব্যক্তিগতভাবে এমন একটি সাবক্লাস ব্যবহার করি wx.Appযার ব্যবহার করে wx.SingleInstanceCheckerএবং যদি অ্যাপ্লিকেশনটির ইতিমধ্যে এর আগে চালিত কোনও বিদ্যমান উদাহরণ উপস্থিত থাকে তবে তা Falseথেকে ফিরে আসে OnInit():

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

এটি wx.Appএকাধিক উদাহরণ নিষিদ্ধ করার জন্য এটি একটি সাধারণ ড্রপ-ইন প্রতিস্থাপন । এটি সহজভাবে প্রতিস্থাপন ব্যবহার করার জন্য wx.Appসঙ্গে SingleAppতাই মত আপনার কোডে:

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

একক সিলেটের জন্য সকেট-তালিকা থ্রেড কোড করার পরে আমি এটি পেয়েছি, যা দুর্দান্ত কাজ করে এবং আমি ইতিমধ্যে একটি দম্পতি প্রোগ্রাম ইনস্টল করেছি, তবে আমি অতিরিক্ত "ওয়েকআপ" চাইলে আমি সিঙ্গেলটনটি দিতে পারি যাতে আমি এটিকে আনতে পারি ওভারল্যাপিং উইন্ডোগুলির একটি বড় স্তূপের সামনে এবং কেন্দ্র। এছাড়াও: "এখানে ডকুমেন্টেড" লিঙ্কটি
চমত্কারভাবে

@ রুফাসভিএস আপনি ঠিক বলেছেন - এটি একটি আরও ভাল ডকুমেন্টেশন লিঙ্ক, উত্তরটি আপডেট করেছে।
ম্যাট কুরব্রু

3

এখানে আমার উইন্ডোজ-শুধুমাত্র সমাধান রয়েছে। নিম্নলিখিতগুলিকে একটি মডিউলে রাখুন, সম্ভবত 'একলোন.পি' বলা হয় বা যাই হোক না কেন। সেই মডিউলটি সরাসরি আপনার __ প্রধান __ অজগর স্ক্রিপ্ট ফাইলে অন্তর্ভুক্ত করুন।

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)

ব্যাখ্যা

কোডটি স্ক্রিপ্টের পুরো পথ থেকে প্রাপ্ত নামের সাথে একটি মিটেক্স তৈরি করার চেষ্টা করে। আসল ফাইল সিস্টেমের সাথে সম্ভাব্য বিভ্রান্তি এড়াতে আমরা ফরোয়ার্ড-স্ল্যাশ ব্যবহার করি।

সুবিধাদি

  • কোনও কনফিগারেশন বা 'যাদু' শনাক্তকারী প্রয়োজন নেই, এটি প্রয়োজন হিসাবে বিভিন্ন স্ক্রিপ্টগুলিতে ব্যবহার করুন।
  • কোনও বাসি ফাইল বাকি নেই, মিউটেক্স আপনার সাথে মারা যায়।
  • অপেক্ষা করার সময় একটি সহায়ক বার্তা মুদ্রণ করে

3

উইন্ডোতে এর জন্য সর্বোত্তম সমাধানটি হ'ল @ জগোদা দ্বারা প্রস্তাবিত মূটেক্সগুলি ব্যবহার করা।

import win32event
import win32api
from winerror import ERROR_ALREADY_EXISTS

mutex = win32event.CreateMutex(None, False, 'name')
last_error = win32api.GetLastError()

if last_error == ERROR_ALREADY_EXISTS:
   print("App instance already running")

কিছু উত্তর ব্যবহার করে fctnl(@ সোরিন টেন্ডো প্যাকেজটিতেও অন্তর্ভুক্ত) যা উইন্ডোজগুলিতে উপলব্ধ নয় এবং আপনার অজগর অ্যাপটি হ'ল এমন প্যাকেজ ব্যবহার pyinstallerকরে স্থির আমদানি করা উচিত, এটি একটি ত্রুটি ছুঁড়ে দেয়।

এছাড়াও, লক ফাইল পদ্ধতি ব্যবহার করে read-onlyডাটাবেস ফাইলগুলির সাথে একটি সমস্যা তৈরি হয় (এটির সাথে এটি অভিজ্ঞ sqlite3)।


2

আমি এটিকে উত্তর হিসাবে পোস্ট করছি কারণ আমি একজন নতুন ব্যবহারকারী এবং স্ট্যাক ওভারফ্লো আমাকে এখনও ভোট দিতে দেবে না।

Sorin Sbarnea এর সমাধানটি ওএস এক্স, লিনাক্স এবং উইন্ডোজ এর অধীনে আমার জন্য কাজ করে এবং আমি এর জন্য কৃতজ্ঞ।

তবে, টেম্পাইল.জেটেম্পডির () ওএস এক্স এবং উইন্ডোজ এর অধীনে একটি উপায় এবং অন্য কিছু / অনেক / সমস্ত (?) * নিক্সের অধীনে আচরণ করে (ওএস এক্সটিও ইউনিক্স! এই বিষয়টি উপেক্ষা করে)। পার্থক্য এই কোডের জন্য গুরুত্বপূর্ণ।

ওএস এক্স এবং উইন্ডোজের ব্যবহারকারী-নির্দিষ্ট টেম্প ডিরেক্টরি রয়েছে, তাই এক ব্যবহারকারী দ্বারা তৈরি একটি টেম্পাইল অন্য ব্যবহারকারীর কাছে দৃশ্যমান নয়। বিপরীতে, * নিক্সের অনেকগুলি সংস্করণের অধীনে (আমি উবুন্টু 9, আরএইচএল 5, ওপেনসোলারিস 2008 এবং ফ্রিবিএসডি 8 পরীক্ষা করেছি), সমস্ত ব্যবহারকারীদের জন্য টেম্প ডিয়ারটি / টিএমপি হয়।

এর অর্থ হ'ল যখন লকফিলটি একটি বহু-ব্যবহারকারী মেশিনে তৈরি করা হয় তখন এটি / টেম্পে তৈরি করা হয় এবং কেবলমাত্র প্রথমবারের মতো লকফিল তৈরি করা ব্যবহারকারীই অ্যাপ্লিকেশনটি চালাতে সক্ষম হবেন।

একটি সম্ভাব্য সমাধান হ'ল লক ফাইলের নামে বর্তমান ব্যবহারকারীর নাম এম্বেড করা।

এটি লক্ষণীয় যে ওপির একটি বন্দরে দখল করার সমাধানটি একটি বহু-ব্যবহারকারী মেশিনেও খারাপ ব্যবহার করবে।


কিছু পাঠকের জন্য (যেমন আমার) কাঙ্ক্ষিত আচরণটি হ'ল কেবলমাত্র একটি অনুলিপি সময়কালে চলতে পারে, নির্বিশেষে কতজন ব্যবহারকারী জড়িত। সুতরাং প্রতি ব্যবহারকারী টিএমপি ডিরেক্টরিগুলি ভাঙ্গা হয়, যখন ভাগ করা / tmp বা পোর্ট লকটি পছন্দসই আচরণ প্রদর্শন করে।
জোনাথন হার্টলে

2

আমি 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


পাই 3 এ ব্যর্থ। প্যাকেজটি ভুল ব্যাখ্যা করা হয়েছে বলে মনে হচ্ছে।
ইকভু

উইন্ডোজ আমি পেয়েছি: আমদানি তদন্ত: fcntl নামে কোনও মডিউল নেই
অ্যান্ড্রু ডব্লিউ ফিলিপস

1

আমি সন্দেহ করছি যে ফাইল সিস্টেমটি আঘাত না করেই প্রক্রিয়া গ্রুপগুলি ব্যবহার করে একটি ভাল পসিমিক সমাধান হওয়া উচিত, তবে আমি এটি পেরেছি না। কিছুটা এইরকম:

প্রারম্ভকালে, আপনার প্রক্রিয়া একটি নির্দিষ্ট গোষ্ঠীর সমস্ত প্রক্রিয়াতে একটি 'কিল -0' প্রেরণ করে। এই জাতীয় কোনও প্রক্রিয়া উপস্থিত থাকলে, এটি প্রস্থান করে। তারপরে এটি গ্রুপে যোগদান করে। অন্য কোনও প্রক্রিয়া সেই গোষ্ঠীটি ব্যবহার করে না।

যাইহোক, এটির একটি দৌড় শর্ত রয়েছে - একাধিক প্রক্রিয়া সমস্ত একই সময়ে একই কাজ করতে পারে এবং সমস্ত গ্রুপে যোগদান করে এবং একই সাথে চলতে পারে। এটিকে জলরোধী করার জন্য আপনি কোনও ধরণের মিউটেক্স যুক্ত করার পরে আপনার আর প্রক্রিয়া গোষ্ঠীগুলির প্রয়োজন হবে না।

এটি যদি আপনার প্রক্রিয়াটি কেবলমাত্র প্রতি মিনিটে বা প্রতি ঘণ্টায় একবার ক্রোন দ্বারা শুরু হয় তবে এটি গ্রহণযোগ্য হতে পারে তবে আপনি যে দিনটি চান না সেদিন এটি ঠিক ভুল হয়ে যাবে।

আমার ধারণা এটি সর্বোপরি খুব ভাল সমাধান নয়, যদি না কেউ এর উন্নতি করতে পারে?


1

আমি গত সপ্তাহে এই সঠিক সমস্যার মধ্যে দৌড়েছি এবং যদিও আমি কিছু ভাল সমাধান খুঁজে পেয়েছি তবে আমি খুব সহজ এবং পরিষ্কার পরিচ্ছন্ন অজগর প্যাকেজ তৈরি করার সিদ্ধান্ত নিয়েছি এবং এটি পিপিআইতে আপলোড করেছি। এটি টেন্ডো থেকে পৃথক যে এটি কোনও স্ট্রিং সংস্থার নাম লক করতে পারে। যদিও আপনি অবশ্যই __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.python.org/pypi/quicklock


1
আমি কেবল এটি "পাইপ ইনস্টল কুইকলক" এর মাধ্যমে ইনস্টল করেছি, তবে যখন আমি "ক্রিকলক আমদানি সিঙ্গলটন" এর মাধ্যমে এটি ব্যবহার করার চেষ্টা করি তখন আমি একটি ব্যতিক্রম পাই: "আমদানি ত্রুটি: নাম 'সিঙ্গলটন' আমদানি করতে পারে না"। এটি একটি ম্যাকের উপর রয়েছে।
গ্রেইয়াই

দেখা যাচ্ছে কুইললক অজগর 3 নিয়ে কাজ করে না That এই কারণেই এটি আমার পক্ষে ব্যর্থ হয়েছিল।
গ্রেইয়াই

হ্যাঁ, দুঃখিত, এটি মোটেও ভবিষ্যতের প্রমাণিত হয়নি। আমি এটির কাজ করার জন্য একটি অবদানকে স্বাগত জানাব!
নাট ফেরেরো

1

রবার্তো রোজারিওর উত্তরের ভিত্তিতে আমি নিম্নলিখিত ফাংশনটি নিয়ে আসছি:

SOCKET = None
def run_single_instance(uniq_name):
    try:
        import socket
        global SOCKET
        SOCKET = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        ## Create an abstract socket, by prefixing it with null.
        # this relies on a feature only in linux, when current process quits, the
        # socket will be deleted.
        SOCKET.bind('\0' + uniq_name)
        return True
    except socket.error as e:
        return False

আমাদের বিশ্বব্যাপী SOCKETস্থিতিশীল সংজ্ঞা দেওয়া দরকার কারণ এটি কেবল তখনই আবর্জনা সংগ্রহ করা হবে যখন পুরো প্রক্রিয়াটি বন্ধ হয়ে যায়। যদি আমরা ফাংশনে কোনও স্থানীয় ভেরিয়েবল ঘোষণা করি তবে এটি ফাংশনটি প্রস্থান করার পরে সুযোগের বাইরে চলে যাবে, সুতরাং সকেটটি মোছা হবে।

সমস্ত কৃতিত্ব রবার্তো রোজারিওর কাছে যাওয়া উচিত, যেহেতু আমি কেবল তার কোডটি স্পষ্ট করেই এবং বিস্তারিতভাবে ব্যাখ্যা করতে পারি। এবং এই কোডটি কেবল লিনাক্সে কাজ করবে, https://troydhanson.github.io/network/Unix_domain_sockets.html থেকে নিম্নলিখিত উদ্ধৃত পাঠ্য হিসাবে ব্যাখ্যা করা হয়েছে:

লিনাক্সের একটি বিশেষ বৈশিষ্ট্য রয়েছে: যদি ইউনিক্স ডোমেন সকেটের পাথের নামটি নাল বাইট \ 0 দিয়ে শুরু হয় তবে ফাইলটির সিস্টেমে এর নাম ম্যাপ করা হবে না। সুতরাং এটি ফাইল সিস্টেমে অন্য নামের সাথে সংঘর্ষ করবে না। এছাড়াও, যখন কোনও সার্ভার তার ইউনিক্স ডোমেন শোনার সকেটটি বিমূর্ত নেমস্পেসে বন্ধ করে দেয়, তখন তার ফাইলটি মুছে ফেলা হয়; নিয়মিত ইউনিক্স ডোমেন সকেটের সাহায্যে ফাইলটি সার্ভারটি বন্ধ করার পরে অবিরত থাকে।


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

1
স্ট্যাক ওভারফ্লোতে স্বাগতম! যদিও এই উত্তরটি সঠিক হতে পারে, দয়া করে কিছু ব্যাখ্যা যুক্ত করুন। অন্তর্নিহিত যুক্তি প্রদর্শন করা কেবল কোড দেওয়ার চেয়ে গুরুত্বপূর্ণ, কারণ এটি ওপি এবং অন্যান্য পাঠকদের এগুলি এবং অনুরূপ বিষয়গুলি নিজেরাই ঠিক করতে সহায়তা করে।
কোডমাউস92

এই থ্রেডসেফ? চেক এবং টেম্প ফাইল তৈরির মতো মনে হচ্ছে পারমাণবিক নয় ...
কপিপিট

0

লিনাক্স সিস্টেমে যে কেউ জিজ্ঞাসা করতে পারে pgrep -a উদাহরণের সংখ্যা করা যায়, স্ক্রিপ্টটি প্রক্রিয়া তালিকায় পাওয়া যায় (বিকল্প -a সম্পূর্ণ কমান্ড লাইনের স্ট্রিংটি প্রকাশ করে)) যেমন

import os
import sys
import subprocess

procOut = subprocess.check_output( "/bin/pgrep -u $UID -a python", shell=True, 
                                   executable="/bin/bash", universal_newlines=True)

if procOut.count( os.path.basename(__file__)) > 1 :        
    sys.exit( ("found another instance of >{}<, quitting."
              ).format( os.path.basename(__file__)))

-u $UIDসীমাবদ্ধতা সমস্ত ব্যবহারকারীর জন্য প্রযোজ্য হবে কিনা তা সরান । দাবি অস্বীকার: ক) ধারণা করা হয় যে স্ক্রিপ্টের (বেস) নামটি অনন্য, খ) জাতিগুলির শর্ত থাকতে পারে।


-1
import sys,os

# start program
try:  # (1)
    os.unlink('lock')  # (2)
    fd=os.open("lock", os.O_CREAT|os.O_EXCL) # (3)  
except: 
    try: fd=os.open("lock", os.O_CREAT|os.O_EXCL) # (4) 
    except:  
        print "Another Program running !.."  # (5)
        sys.exit()  

# your program  ...
# ...

# exit program
try: os.close(fd)  # (6)
except: pass
try: os.unlink('lock')  
except: pass
sys.exit()  

2
স্ট্যাক ওভারফ্লোতে স্বাগতম! যদিও এই কোড ব্লকটি প্রশ্নের উত্তর দিতে পারে, আপনি কেন এটি করেন কেন তার জন্য একটু ব্যাখ্যা সরবরাহ করতে পারলে ভাল হবে be এই জাতীয় বিবরণ অন্তর্ভুক্ত করতে দয়া করে আপনার উত্তরটি সম্পাদনা করুন।
আর্টজম বি।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.