পাইথনে কীবোর্ড ইন্টারটারপেট ক্যাপচার ব্যতীত চেষ্টা করুন


101

সেখানে ক্যাপচার করার পাইথন মধ্যে কিছু উপায় আছে কি KeyboardInterruptএকটি ভিতরে সমস্ত কোড নির্বাণ ছাড়া ঘটনা try- exceptবক্তব্য?

যদি ব্যবহারকারীরা Ctrl+ টিপেন তবে আমি পরিষ্কারভাবে ট্রেস ছাড়াই প্রস্থান করতে চাই C

উত্তর:


149

হ্যাঁ, আপনি একটি ইন্টারাপ্ট হ্যান্ডলার মডিউল ব্যবহার করে ইনস্টল করতে পারেন সংকেত , এবং একটি ব্যবহার চিরকাল অপেক্ষা threading.Event :

import signal
import sys
import time
import threading

def signal_handler(signal, frame):
    print('You pressed Ctrl+C!')
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
forever = threading.Event()
forever.wait()

10
মনে রাখবেন যে সিগন্যাল মডিউল নিয়ে কিছু প্ল্যাটফর্ম-নির্দিষ্ট সমস্যা রয়েছে - এই পোস্টারটিকে প্রভাবিত করা উচিত নয়, তবে "উইন্ডোজ অন, সিগন্যাল () কেবলমাত্র স্যাব্যাবআরটি, সিআইজিএফপি, সিগিল, সিগিন্ট, সিগসাইজিভি বা সিগিটারএম দিয়ে কল করা যেতে পারে A অন্য যে কোনও ক্ষেত্রে উত্থাপিত হবে। "
বিজিপিটার

7
থ্রেড দিয়েও ভাল কাজ করে। আমি আশা করি আপনি কখনও করবেন না while True: continue, যদিও। (এই স্টাইলে, while True: passযাই হোক না কেন পরিষ্কার হবে)) এটি খুব অপচয় হবে; এর মতো কিছু চেষ্টা করুন while True: time.sleep(60 * 60 * 24)(একসাথে একদিনের জন্য ঘুমানো একটি সম্পূর্ণ স্বেচ্ছাচারী চিত্র)।
ক্রিস মরগান

1
আপনি যদি ক্রিস মরগানের পরামর্শটি ব্যবহার করার পরামর্শটি ব্যবহার করেন time(তবে যেমনটি আপনার উচিত ছিল) তবে ভুলে যাবেন না import time:)
সিউক্স

1
Sys.exit (0) কল করা আমার জন্য একটি SystemExit ব্যতিক্রম ট্রিগার করে। : আপনি এটি চমত্কারভাবে কাজ যদি আপনার সাথে এই একযোগে এটি ব্যবহার করতে পারেন stackoverflow.com/a/13723190/353094
leetNightshade

2
পরিবর্তে আপনি বারবার ঘুমের signal.pause (ব্যবহার করতে পারেন)
Croad Langshan

36

যদি আপনি যা চান তা হ'ল ট্রেসব্যাক না দেখানো, আপনার কোডটি এইভাবে তৈরি করুন:

## all your app logic here
def main():
   ## whatever your app does.


if __name__ == "__main__":
   try:
      main()
   except KeyboardInterrupt:
      # do nothing here
      pass

(হ্যাঁ, আমি জানি যে এটি সরাসরি প্রশ্নের উত্তর দেয় না, তবে ব্লক ব্যতীত কেন চেষ্টা করা দরকার তা আপত্তিজনক - সম্ভবত এটি ওপিকে কম বিরক্তিকর করে তোলে)


5
কিছু কারণে, এটি সবসময় আমার পক্ষে কাজ করে না। signal.signal( signal.SIGINT, lambda s, f : sys.exit(0))সর্বদা না।
হাল ক্যানারি

এটি সর্বদা পাইগটেকের মতো থ্রেড ব্যবহার করে এমন জিনিসগুলির সাথে কাজ করে না। কখনও কখনও ^ C পুরো প্রক্রিয়াটির পরিবর্তে কেবল বর্তমান থ্রেডটি মেরে ফেলবে, তাই ব্যতিক্রম কেবলমাত্র এই থ্রেডের মাধ্যমেই প্রচার করবে।
সুডো বাশ

: অন্য তাই প্রশ্ন pygtk সঙ্গে সম্পর্কে জন্য Ctrl + সি বিশেষভাবে এর stackoverflow.com/questions/16410852/...
bgporter

30

আপনার নিজস্ব সিগন্যাল হ্যান্ডলারটি সেট করার বিকল্প হ'ল ব্যতিক্রমটি ধরতে এবং এটিকে উপেক্ষা করার জন্য একটি প্রসঙ্গ-পরিচালক ব্যবহার করা:

>>> class CleanExit(object):
...     def __enter__(self):
...             return self
...     def __exit__(self, exc_type, exc_value, exc_tb):
...             if exc_type is KeyboardInterrupt:
...                     return True
...             return exc_type is None
... 
>>> with CleanExit():
...     input()    #just to test it
... 
>>>

এটি কী চলছে তার কিছু স্পষ্ট উল্লেখ সংরক্ষণ করে try- exceptব্লকটিকে সরিয়ে দেয় ।

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


1
চমৎকার, সংকেত নিয়ে কাজ করার চেয়ে উদ্দেশ্যটি প্রকাশের ক্ষেত্রে এই সমাধানটি আরও কিছুটা প্রত্যক্ষ বলে মনে হচ্ছে।
সাউक्स

মাল্টিপ্রসেসিং লাইব্রেরি ব্যবহার করে, আমি নিশ্চিত না যে আমার কোন অবজেক্টে এই পদ্ধতিগুলি যুক্ত করা উচিত .. কোনও ক্লু?
স্টাফেন

@ স্টাফেন আপনার অর্থ কী? মাল্টিপ্রসেসিংয়ের সাথে কাজ করার সময় আপনাকে পিতা বা মাতা এবং সন্তানের উভয় প্রক্রিয়ায় সংকেত নিয়ে কাজ করতে হবে, যেহেতু এটি উভয় ক্ষেত্রেই ট্রিগার হতে পারে। এটি আসলে আপনি কী করছেন এবং আপনার সফ্টওয়্যার কীভাবে ব্যবহৃত হবে তার উপর নির্ভর করে।
বকুরিউ

8

আমি জানি এটি একটি পুরানো প্রশ্ন তবে আমি এখানে প্রথমে এসে atexitমডিউলটি আবিষ্কার করেছি । আমি এর ক্রস-প্ল্যাটফর্ম ট্র্যাক রেকর্ড বা ক্যাভ্যাটগুলির সম্পূর্ণ তালিকা সম্পর্কে এখনও জানি না, তবে এখনও অবধি KeyboardInterruptলিনাক্স -এ পোস্ট- ক্লিনআপ হ্যান্ডেল করার চেষ্টা করেছিলাম ঠিক এটিই । সমস্যাটির কাছে যাওয়ার আরও একটি উপায় ছুঁড়ে ফেলতে চেয়েছিলেন।

আমি তারেক ক্রিয়াকলাপের প্রসঙ্গে পোস্ট-প্রস্থান এক্স-ক্লিন-আপ করতে চাই, তাই try/ এ সমস্ত কিছু মোড়ানো exceptআমার পক্ষেও বিকল্প ছিল না। atexitআপনার কোডটি নিয়ন্ত্রণের প্রবাহের শীর্ষ স্তরে নয় এমন পরিস্থিতিতে আমার মনে হতে পারে such

atexit বাক্সের বাইরে খুব সক্ষম এবং পাঠযোগ্য, উদাহরণস্বরূপ:

import atexit

def goodbye():
    print "You are now leaving the Python sector."

atexit.register(goodbye)

আপনি এটি একটি ডেকোরেটর হিসাবেও ব্যবহার করতে পারেন (২.6 হিসাবে; ডক্স থেকে এই উদাহরণটি):

import atexit

@atexit.register
def goodbye():
    print "You are now leaving the Python sector."

আপনি যদি এটি KeyboardInterruptকেবলমাত্র নির্দিষ্ট করতে চান তবে এই প্রশ্নের উত্তর অন্য কোনও ব্যক্তির উত্তর সম্ভবত আরও ভাল।

তবে নোট করুন যে atexitমডিউলটি কেবল কোডের 70 ডলার লাইন এবং ব্যতিক্রমগুলি আলাদাভাবে বিবেচনা করে এমন একটি অনুরূপ সংস্করণ তৈরি করা কঠিন হবে না, উদাহরণস্বরূপ কলব্যাক ফাংশনে আর্গুমেন্ট হিসাবে ব্যতিক্রমগুলি পাস করা passing (এর সীমাবদ্ধতা atexitএকটি পরিবর্তিত সংস্করণকে ওয়ারেন্ট করবে: বর্তমানে আমি ব্যতিক্রম সম্পর্কে জানতে এক্সিট-কলব্যাক-ফাংশনগুলির জন্য কোনও উপায় কল্পনা করতে পারি না; atexitহ্যান্ডলার ব্যতিক্রমটি ধরবে , আপনার কলব্যাক (গুলি) কল করে আবার পুনরায় উত্থাপন করবে) ব্যতিক্রম। তবে আপনি এটি অন্যভাবে করতে পারতেন))

আরও তথ্যের জন্য দেখুন:


atexit 'কিবোর্ড ইন্টারটার্প্ট (অজগর 3.7) এর জন্য কাজ করে না
টিমজামান

এখানে কীবোর্ড ইন্টারটারপেটের জন্য কাজ করেছেন (অজগর 3.7, ম্যাকোস)। প্ল্যাটফর্ম-নির্দিষ্ট কোচ?
নিকো নাইম্যান

4

আপনি (সর্বাধিক সুস্পষ্ট এবং প্রস্তাবিত "সেরা" সমাধান KeyboardInterruptছাড়াই try: ... except KeyboardInterrupt: pass) স্ট্যাক ট্রেস প্রিন্টিং প্রতিরোধ করতে পারেন তবে প্রতিস্থাপন করে আপনি এটি ইতিমধ্যে জানেন এবং অন্য কিছু চেয়েছিলেন) sys.excepthook। কিছুটা এইরকম

def custom_excepthook(type, value, traceback):
    if type is KeyboardInterrupt:
        return # do nothing
    else:
        sys.__excepthook__(type, value, traceback)

আমি ব্যবহারকারী সিটিআরএল-সি চাপলে ট্রেস ছাড়াই পরিষ্কার প্রস্থান চাই
অ্যালেক্স

7
এই সব সত্য নয়। একটি বাধা হ্যান্ডলারের সময় কীবোর্ড আন্তঃবিধ ব্যতিক্রম তৈরি করা হয়। সিগিন্টের জন্য ডিফল্ট হ্যান্ডলারটি কীবোর্ড ইন্টারটার্প্ট উত্থাপন করে তাই আপনি যদি আচরণটি না চান তবে আপনাকে যা করতে হবে তা হ'ল সাইন্টের জন্য একটি আলাদা সিগন্যাল হ্যান্ডলার সরবরাহ করতে। আপনার ক্ষেত্রে সঠিক যে ব্যতিক্রমগুলি কেবলমাত্র একটি চেষ্টা করে পরিচালনা করা যায় / তবে এই ক্ষেত্রে আপনি ব্যতিক্রমটিকে প্রথম স্থানে উত্থাপিত থেকে বজায় রাখতে পারেন।
ম্যাট

1
হ্যাঁ, আমি শিখেছি যে পোস্ট করার প্রায় তিন মিনিট পরে, যখন কোটলিনস্কির উত্তরটি গড়িয়ে পড়ে;)

2

আমি প্রত্যেকের দ্বারা প্রস্তাবিত সমাধানগুলি চেষ্টা করেছিলাম, তবে আসলে এটি কার্যকর করার জন্য আমাকে নিজের কোডটি তৈরি করতে হয়েছিল। নিম্নলিখিতটি আমার অস্থায়ী কোড:

import signal
import sys
import time

def signal_handler(signal, frame):
    print('You pressed Ctrl+C!')
    print(signal) # Value is 2 for CTRL + C
    print(frame) # Where your execution of program is at moment - the Line Number
    sys.exit(0)

#Assign Handler Function
signal.signal(signal.SIGINT, signal_handler)

# Simple Time Loop of 5 Seconds
secondsCount = 5
print('Press Ctrl+C in next '+str(secondsCount))
timeLoopRun = True 
while timeLoopRun:  
    time.sleep(1)
    if secondsCount < 1:
        timeLoopRun = False
    print('Closing in '+ str(secondsCount)+ ' seconds')
    secondsCount = secondsCount - 1

0

যদি কেউ দ্রুত ন্যূনতম সমাধানের সন্ধানে থাকে তবে

import signal

# The code which crashes program on interruption

signal.signal(signal.SIGINT, call_this_function_if_interrupted)

# The code skipped if interrupted
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.