পাইথনের থ্রেডের ভিতরে ডাকলে কেন sys.exit () প্রস্থান করে না?


101

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

import sys, time
from threading import Thread

def testexit():
    time.sleep(5)
    sys.exit()
    print "post thread exit"

t = Thread(target = testexit)
t.start()
t.join()
print "pre main exit, post thread exit"
sys.exit()
print "post main exit"

Sys.exit () এর জন্য দস্তাবেজগুলি জানিয়েছে যে কলটি পাইথন থেকে প্রস্থান করা উচিত। আমি এই প্রোগ্রামটির আউটপুট থেকে দেখতে পাচ্ছি যে "পোস্ট থ্রেড প্রস্থান" কখনই মুদ্রিত হয় না, তবে মূল থ্রেড থ্রেড কলগুলি প্রস্থান করার পরেও চলতে থাকে।

প্রতিটি থ্রেডের জন্য দোভাষী আলাদা আলাদা উদাহরণ তৈরি করা হচ্ছে, এবং প্রস্থান করার জন্য কলটি () কেবল সেই পৃথক দৃষ্টান্তটি থেকে বেরিয়ে আসছে? যদি তা হয় তবে থ্রেডিং বাস্তবায়ন কীভাবে ভাগ করা সংস্থানগুলিতে অ্যাক্সেস পরিচালনা করে? আমি যদি থ্রেড থেকে প্রোগ্রামটি বেরিয়ে যেতে চাই না (তবে আমি আসলে যা চাই তা নয়, তবে কেবল আমি বুঝতে পারি)?

উত্তর:


74

sys.exit()SystemExitব্যতিক্রম উত্থাপন , যেমন করে thread.exit()। সুতরাং, যখন sys.exit()সেই থ্রেডের অভ্যন্তরে সেই ব্যতিক্রম উত্থাপন করা হয় , তখন এটি কল করার মতোই প্রভাব ফেলেছিল thread.exit(), এই কারণেই কেবল থ্রেডটি প্রস্থান করে।


25

আমি যদি থ্রেড থেকে প্রোগ্রামটি প্রস্থান করতে চান না?

ডিস্টান বর্ণিত পদ্ধতি ছাড়াও আপনি কল করতে পারেন os._exit(আন্ডারস্কোরটি লক্ষ্য করুন)। এটি ব্যবহারের আগে নিশ্চিত হয়ে নিন যে আপনি বুঝতে পেরেছেন যে এটি কোনও ক্লিনআপ করে না (যেমন কলিং __del__বা অনুরূপ)।


4
এটা কি I / O ফ্লাশ করবে?
লরেঞ্জো বেলি

4
os._exit (n): "ক্লিনআপ হ্যান্ডলারদের কল না করা, স্টিডিও বাফারগুলি ফ্লাশিং ইত্যাদিতে স্ট্যাটাস এন দিয়ে প্রক্রিয়াটি প্রস্থান করুন" "
টিম রিচার্ডসন

নোট করুন যে যখন os._exitঅভিশাপগুলির মধ্যে ব্যবহার করা হয় তখন কনসোলটি এটির সাথে কোনও স্বাভাবিক অবস্থায় পুনরায় সেট করা হয় না। আপনি চালানো আছে resetইউনিক্স-শেল মধ্যে এই সমাধানের জন্য।
sjngm

25

আমি যদি থ্রেড থেকে প্রোগ্রামটি প্রস্থান করতে চান না?

লিনাক্সের জন্য:

os.kill(os.getpid(), signal.SIGINT)

এটি SIGINTমূল থ্রেডকে প্রেরণ করে যা একটি উত্থাপন করে KeyboardInterrupt। এটির সাথে আপনার একটি সঠিক পরিচ্ছন্নতা আছে। এছাড়াও আপনি কোনও হ্যান্ডলার নিবন্ধভুক্ত করতে পারেন, আপনি যদি অন্যরকম প্রতিক্রিয়া জানাতে চান।

উপরের উইন্ডোজে কাজ করে না, কারণ আপনি কেবল একটি SIGTERMসংকেত পাঠাতে পারেন , যা পাইথন দ্বারা পরিচালিত হয় না এবং এর মতোই প্রভাব ফেলে sys._exit()

উইন্ডোজ জন্য:

তুমি ব্যবহার করতে পার:

sys._exit()

এটি পুরো প্রক্রিয়াটি থেকে প্রস্থান করবে। তবে কোনও ক্লিনআপ ছাড়াই। আপনার যদি এটির প্রয়োজন হয় তবে আপনাকে অন্যভাবে মূল থ্রেডের সাথে যোগাযোগ করতে হবে।


4
এছাড়াও os._exit
sjngm

12

"প্রাক প্রধান প্রস্থান, পোস্ট থ্রেড প্রস্থান" ছাপানো হয়েছে কি তা আপনাকে বিরক্ত করছে?

কিছু অন্যান্য ভাষার (জাভা যেমন) এর বিপরীতে যেখানে এনালগটি sys.exit( System.exitজাভার ক্ষেত্রে) সাথে সাথে ভিএম / প্রসেস / ইন্টারপ্রেটারকে তাত্ক্ষণিকভাবে থামিয়ে তোলে, পাইথনের sys.exitকেবল একটি ব্যতিক্রম ছুঁড়েছে: বিশেষত একটি সিস্টেমএক্সিট ব্যতিক্রম।

এখানে sys.exit(ন্যায্য print sys.exit.__doc__) জন্য দস্তাবেজগুলি এখানে রয়েছে :

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

এর কয়েকটি পরিণতি রয়েছে:

  • একটি থ্রেডে এটি কেবলমাত্র বর্তমান থ্রেডটিকে হত্যা করে, পুরো প্রক্রিয়াটি নয় (ধরে নিলে এটি স্ট্যাকের শীর্ষে চলে গেছে ...)
  • অবজেক্ট ডেস্ট্রাক্টর ( __del__) সম্ভাব্যভাবে স্ট্যাক ফ্রেম হিসাবে আহ্বান করা হয় যা এই বস্তুগুলিকে অযৌক্তিক বলে উল্লেখ করে
  • অবশেষে ব্লকগুলি স্ট্যাক আনওয়াইন্ডস হিসাবে কার্যকর করা হয়
  • আপনি একটি SystemExitব্যতিক্রম ধরতে পারেন

শেষটি সম্ভবত সবচেয়ে আশ্চর্যজনক এবং এটি অন্য কারণ exceptযা আপনার পাইথন কোডে প্রায় কোনও অযোগ্য বিবৃতি না পাওয়া উচিত ।


12

আমি যদি থ্রেড থেকে প্রোগ্রামটি বেরিয়ে যেতে চাই না (তবে আমি আসলে যা চাই তা নয়, তবে কেবল আমি বুঝতে পারি)?

আমার পছন্দের পদ্ধতিটি হ'ল এরলং-ইশ বার্তা প্রেরণ। সামান্যভাবে সিমিলাইফড, আমি এটি এটি করি:

import sys, time
import threading
import Queue # thread-safe

class CleanExit:
  pass

ipq = Queue.Queue()

def testexit(ipq):
  time.sleep(5)
  ipq.put(CleanExit)
  return

threading.Thread(target=testexit, args=(ipq,)).start()
while True:
  print "Working..."
  time.sleep(1)
  try:
    if ipq.get_nowait() == CleanExit:
      sys.exit()
  except Queue.Empty:
    pass

4
আপনার Queueএখানে দরকার নেই। শুধু একটি সহজ boolজরিমানা করতে হবে। এই ভেরিয়েবলের ক্লাসিক নাম is_activeএবং এটির প্রাথমিক ডিফল্ট মান True
একিউম্যানাস

4
হ্যাঁ আপনি সঠিক. Effbot.org/zone/thread-synchronization.htm এর মতে , একটি bool(বা অন্য কোনও পারমাণবিক অপারেশন) পরিবর্তন করা এই বিশেষ সমস্যার জন্য পুরোপুরি কার্যকর করবে। কারনেই আমি সঙ্গে যেতে Queueগুলি যে যখন থ্রেডেড এজেন্টদের সঙ্গে কাজ আমি বিভিন্ন সংকেত প্রয়োজন শেষ প্রবণতা আছে ( flush, reconnect, exit, ইত্যাদি ...) প্রায় সঙ্গে সঙ্গেই।
ডিস্টান

4
ডিস্টান: যেহেতু bool@ অ্যাকুয়ামনাস নির্দেশ করেছেন, যেহেতু একটি কাজ করবে, তেমনি একইভাবে একটি সরল intমনে হতে পারে যে বিভিন্ন সংকেত পরিচালনা করতে সক্ষম হওয়া দরকার - সর্বোপরি boolকেবল একটি সাবক্লাস int
মার্টিনিউ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.