আইওআরর: [এর্নো 32] ভাঙা পাইপ: পাইথন


91

আমার কাছে খুব সাধারণ পাইথন 3 স্ক্রিপ্ট রয়েছে:

f1 = open('a.txt', 'r')
print(f1.readlines())
f2 = open('b.txt', 'r')
print(f2.readlines())
f3 = open('c.txt', 'r')
print(f3.readlines())
f4 = open('d.txt', 'r')
print(f4.readlines())
f1.close()
f2.close()
f3.close()
f4.close()

তবে এটি সর্বদা বলে:

IOError: [Errno 32] Broken pipe

আমি এটি ঠিক করার সমস্ত জটিল পদ্ধতি ইন্টারনেটে দেখেছি, তবে আমি এই কোডটি সরাসরি অনুলিপি করেছি, তাই আমি মনে করি যে কোডটিতে কিছু ভুল আছে এবং পাইথনের সিগপিপ নয়।

আমি আউটপুটটিকে পুনর্নির্দেশ করছি, সুতরাং উপরের স্ক্রিপ্টটির নাম যদি "ওপেন.পি" হয়, তবে আমার চালনার আদেশটি হ'ল:

open.py | othercommand

@squiguy লাইন 2:print(f1.readlines())
JOHANNES_NYÅTT

4
আপনি লাইনে 2 তে দুটি আইও অপারেশন পেয়েছেন: একটি পাঠানো a.txtএবং এতে লেখা stdout। সম্ভবত সেগুলি পৃথক রেখায় বিভক্ত করার চেষ্টা করুন যাতে আপনি দেখতে পাচ্ছেন কোন অপারেশন ব্যতিক্রমটিকে ট্রিগার করে। যদি stdoutকোনও পাইপ হয় এবং পড়ার শেষটি বন্ধ হয়ে যায়, তবে এটি EPIPEত্রুটির জন্য অ্যাকাউন্ট হতে পারে ।
জেমস হেনস্ট্রিজ

4
আমি এই ত্রুটিটি আউটপুটে পুনরুত্পাদন করতে পারি (সঠিক শর্ত দেওয়া হয়েছে), সুতরাং আমি সন্দেহ করি যে printকলটি অপরাধী। @ জোহনেস_এনওয়াইটিটি, আপনি কীভাবে আপনার পাইথন স্ক্রিপ্ট চালু করছেন তা আপনি পরিষ্কার করে বলতে পারেন? আপনি কোথাও স্ট্যান্ডার্ড আউটপুট পুনর্নির্দেশ করছেন?
ব্ল্যাকঙ্কহট

4
এই নিচের প্রশ্নগুলোর একটি সম্ভাব্য সদৃশ stackoverflow.com/questions/11423225/...

উত্তর:


48

আমি সমস্যাটি পুনরায় তৈরি করি নি, তবে সম্ভবত এই পদ্ধতিটি এটিকে সমাধান করবে: ( stdoutব্যবহারের চেয়ে লাইনে লাইন লিখে print)

import sys
with open('a.txt', 'r') as f1:
    for line in f1:
        sys.stdout.write(line)

তুমি কি ভাঙা পাইপ ধরতে পার? stdoutপাইপ বন্ধ না হওয়া পর্যন্ত এটি ফাইলটিকে লাইনে লিখে দেয় writes

import sys, errno
try:
    with open('a.txt', 'r') as f1:
        for line in f1:
            sys.stdout.write(line)
except IOError as e:
    if e.errno == errno.EPIPE:
        # Handle error

othercommandপাইপটি খুব বড় হওয়ার আগে অবশ্যই এটি পড়তে হবে তা আপনাকেও নিশ্চিত করতে হবে - /unix/11946/how-big-is-tip-puff-buffer


7
যদিও এটি একটি ভাল প্রোগ্রামিং অনুশীলন, আমি মনে করি না যে এটির ভাঙ্গা পাইপের ত্রুটিটি প্রশ্নকর্তাটি পেয়ে যাচ্ছেন (যা সম্ভবত printকলটির সাথে করতে হবে, ফাইলগুলি পড়ার সাথে নয়) anything
ব্ল্যাকঙ্কহট

@ ব্ল্যাককিএনএইচটি আমি কয়েকটি প্রশ্ন এবং বিকল্প পদ্ধতি যুক্ত করেছি এবং লেখকের কাছ থেকে কিছু প্রতিক্রিয়া আশা করছি। যদি সমস্যাটি একটি মুক্ত ফাইল থেকে সরাসরি মুদ্রণ বিবৃতিতে ডেটা প্রেরণ করে তবে উপরের বিকল্পগুলির মধ্যে একটি এটি ঠিক করতে পারে।
অ্যালেক্স এল

(সহজ সমাধানগুলি প্রায়শই সেরা - যদি একটি সম্পূর্ণ ফাইল লোড করার নির্দিষ্ট কারণ না থাকে তবে এটি মুদ্রণ করুন, এটি অন্যভাবে করুন)
অ্যালেক্স এল

4
এটি সমস্যার সমাধানে দুর্দান্ত কাজ! যদিও আমি এই উত্তরটিকে সম্মানজনকভাবে নিতে পেরেছি, অন্য উত্তরগুলি (এবং আমার নিজস্ব পদ্ধতির) কীভাবে আপনার উত্তরটির তুলনায় তুলনা করা হয়েছে তা দেখার পরেই আমি এটির প্রশংসা করতে পারি।
জেসভিন জোস

117

SIGPIPE হ্যান্ডলিংয়ের কারণে সমস্যা। আপনি নিম্নলিখিত কোডটি ব্যবহার করে এই সমস্যাটি সমাধান করতে পারেন:

from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE,SIG_DFL) 

এই সমাধানের পটভূমি জন্য এখানে দেখুন । ভাল উত্তর এখানে


14
এটি অত্যন্ত বিপজ্জনক, যেমনটি আমি সবেমাত্র আবিষ্কার করেছি, কারণ আপনি যদি কখনও সকেটে (HTTP বা অন্য কোনও কিছু) সাইনপাইপ পান তবে আপনার প্রোগ্রামটি সতর্কতা বা ত্রুটি ছাড়াই প্রস্থান করবে।
ডেভিড বেনেট

4
@ ডেভিডবেনেট, আমি নিশ্চিত যে এর প্রয়োগ নির্ভরশীল এবং আপনার উদ্দেশ্যে গৃহীত উত্তরটি সঠিক one লোকেরা যেতে এবং একটি সিদ্ধান্তযুক্ত সিদ্ধান্ত নেওয়ার জন্য এখানে অনেক পুঙ্খানুপুঙ্খ প্রশ্নোত্তর রয়েছে । আইএমও, কমান্ড লাইন সরঞ্জামগুলির জন্য, বেশিরভাগ ক্ষেত্রে পাইপ সংকেত উপেক্ষা করা সম্ভবত সেরা।
আখন

4
কেবলমাত্র অস্থায়ীভাবে এটি করার কোনও উপায়?
নেট গ্লেন

4
@ নেটগ্লেন আপনি বিদ্যমান হ্যান্ডলারটি সংরক্ষণ করতে পারেন এবং এটি পরে পুনরুদ্ধার করতে পারেন ।
akhan

4
কেউ আমাকে উত্তর দিতে পারেন কেন লোকেরা দাপ্তরিক ডকুমেন্টেশনের চেয়ে ব্লগস্পট নিবন্ধকে সত্যের আরও ভাল উত্স হিসাবে বিবেচনা করছেন (ইঙ্গিত: ভাঙা পাইপের ত্রুটি সঠিকভাবে কীভাবে ঠিক করবেন তা দেখার জন্য লিঙ্কটি খুলুন)? :)
ইউরি রবিস্কো

93

আনার জন্য অ্যালেক্স এল এর সহায়ক উত্তর , akhan এর সহায়ক উত্তর , এবং Blckknght এর সহায়ক উত্তর কিছু অতিরিক্ত তথ্য একসাথে:

  • SIGPIPEপাইপ থেকে কোনও প্রক্রিয়া পড়ার প্রক্রিয়া না থাকলে স্ট্যান্ডার্ড ইউনিক্স সিগন্যালটি কোনও পাইপে লিখিত প্রক্রিয়াতে প্রেরণ করা হয় anymore

    • এটি অগত্যা কোনও ত্রুটির শর্ত নয়; কিছু ইউনিক্স ইউটিলিটি যেমন head ডিজাইন দ্বারা পর্যাপ্ত ডেটা প্রাপ্ত হওয়ার পরে পাইপ থেকে অকাল পড়া বন্ধ করে দেয়।
  • ডিফল্টরূপে - অর্থাত্, যদি লেখার প্রক্রিয়াটি স্পষ্টভাবে ফাঁদে না যায় SIGPIPE- লেখার প্রক্রিয়াটি কেবল সমাপ্ত হয় এবং এর প্রস্থান কোড সেট করা হয়141 , যা গণনা করা হয় 128(সাধারণভাবে সংকেত দ্বারা সমাপ্তির লক্ষণ হিসাবে ) + 13( SIGPIPEএর নির্দিষ্ট সংকেত সংখ্যা ) ।

  • নকশা দ্বারা, পাইথন নিজেই ফাঁদে পড়েSIGPIPE এবং এটিকেIOErrorerrno মূল্যের সাথে পাইথন উদাহরণে অনুবাদ করেerrno.EPIPE , যাতে পাইথনের লিপিটি এটি চয়ন করতে পারে, যদি এটি পছন্দ করে - এটি কীভাবে করবেন তার জন্য অ্যালেক্স এল এর উত্তর দেখুন

  • একটি পাইথন যদি স্ক্রিপ্ট নেই না এটা ধরতে , পাইথন আউটপুট ত্রুটি বার্তাIOError: [Errno 32] Broken pipe এবং প্রস্থান কোড সহ স্ক্রিপ্ট বন্ধ1 - এই উপসর্গ ওপি করাত হয়।

  • অনেক ক্ষেত্রে এটি সহায়কের চেয়ে আরও বিঘ্নজনক , তাই ডিফল্ট আচরণে ফিরে যাওয়া বাঞ্ছনীয় :

    • signalমডিউলটি ব্যবহার করা ঠিক তা করতে দেয়, যেমন আখনের উত্তরে বলা হয়েছে ; signal.signal()1 ম আর্গুমেন্ট হিসাবে হ্যান্ডেল এবং 2 য় হিসাবে একটি হ্যান্ডলার গ্রহণ করে; বিশেষ হ্যান্ডলার মান SIG_DFLসিস্টেমের ডিফল্ট আচরণকে উপস্থাপন করে :

      from signal import signal, SIGPIPE, SIG_DFL
      signal(SIGPIPE, SIG_DFL) 
      

32

যখন আপনি অন্য প্রান্তে বন্ধ হয়ে যাওয়া পাইপটিতে লেখার চেষ্টা করবেন তখন একটি "ব্রোকন পাইপ" ত্রুটি ঘটে। যেহেতু আপনি দেখিয়েছেন কোডটি কোনও পাইপ সরাসরি জড়িত না, তাই আমি সন্দেহ করি যে আপনি পাইথনের বাইরের কিছু করছেন পাইথন ইন্টারপ্রেটারের স্ট্যান্ডার্ড আউটপুট অন্য কোথাও পুনর্নির্দেশের জন্য। আপনি যদি স্ক্রিপ্টটি চালাচ্ছেন তবে এটি ঘটতে পারে:

python foo.py | someothercommand

আপনার কাছে সমস্যাটি someothercommandহ'ল এটির স্ট্যান্ডার্ড ইনপুটটিতে উপলভ্য সমস্ত কিছুই না পড়েই প্রস্থান করা হচ্ছে । এটি আপনার লেখার (মাধ্যমে print) কোনও সময়ে ব্যর্থ হতে পারে।

আমি লিনাক্স সিস্টেমে নিম্নলিখিত কমান্ডটি দিয়ে ত্রুটিটি পুনরুত্পাদন করতে সক্ষম হয়েছি:

python -c 'for i in range(1000): print i' | less

যদি আমি lessপেজারটি এর সমস্ত ইনপুট (1000 লাইন) এর মাধ্যমে স্ক্রল না করেই বন্ধ করে রাখি তবে পাইথন IOErrorআপনি যেই প্রতিবেদন করেছেন তা দিয়ে বেরিয়ে আসে ।


10
হ্যাঁ, এটি সত্য, তবে কীভাবে আমি এটি ঠিক করব?
JOHANNES_NYÅTT

4
এটি ঠিক করতে দয়া করে আমাকে জানান।
JOHANNES_NYÅTT

4
@ জোহনেস_এনওয়াইটিটি: বেশিরভাগ ইউনিক্সের মতো সিস্টেমে পাইপ সরবরাহকারী বাফারিংয়ের কারণে এটি ছোট ফাইলগুলির জন্য কাজ করতে পারে। আপনি যদি বাফারে ফাইলগুলির সম্পূর্ণ বিষয়বস্তু লিখতে পারেন তবে অন্য প্রোগ্রামটি কখনই সেই ডেটা না পড়লে ত্রুটি বাড়ে না। তবে, যদি লেখার ব্লকগুলি (কারণ বাফার পূর্ণ থাকে), তবে অন্য প্রোগ্রামটি প্রস্থান করলে এটি ব্যর্থ হবে। আবার বলার জন্য: অন্য আদেশটি কী? আমরা কেবল পাইথন কোড দিয়ে আপনাকে আর কোনও সহায়তা করতে পারি না (যেহেতু এটি যে অংশটি ভুল কাজ করছে তা নয়)।
ব্ল্যাকঙ্কহাত

4
মাথায় যাওয়ার সময় পাইপিংয়ের সময় আমি এই সমস্যাটি পেয়েছি ... দশ লাইন আউটপুট পরে ব্যতিক্রম। বেশ যৌক্তিক, তবে এখনও অপ্রত্যাশিত :)
আন্দ্রে লাসজলো

4
@Blckknght: সাধারণভাবে ভাল তথ্য, কিন্তু পুনরায় " ফিক্স যে: এবং" অংশ করছে ভুল জিনিস ": একটি SIGPIPEসংকেত অগত্যা একটি নির্দেশ করে না ত্রুটি শর্ত; কিছু ইউনিক্স ইউটিলিটিগুলি, উল্লেখযোগ্য হল head, নকশা, স্বাভাবিক অপারেশনের সময় ঘনিষ্ঠ নল গোড়ার দিকে, যেমন একবার তারা অনেক তথ্য হিসাবে পড়েছি তারা প্রয়োজন ছিল।
mklement0

21

আমি যে পদ্ধতিটি ব্যবহার করে তা নির্দেশ করতে বাধ্য feel

signal(SIGPIPE, SIG_DFL) 

সত্যই বিপজ্জনক (যেমন ইতিমধ্যে মন্তব্যগুলিতে ডেভিড বেনেট পরামর্শ দিয়েছিলেন) এবং আমার ক্ষেত্রে প্ল্যাটফর্ম নির্ভর মজার ব্যবসায়ের দিকে পরিচালিত হয় যখন একত্রিত হয়ে যায় multiprocessing.Manager(কারণ স্ট্যান্ডার্ড লাইব্রেরি ব্রোকনপাইপ এরর উপর নির্ভর করে বেশ কয়েকটি জায়গায় উত্থাপিত হয়)। একটি দীর্ঘ এবং বেদনাদায়ক গল্পটি ছোট করার জন্য, আমি এটি এটি ঠিক করেছি:

প্রথমত, আপনাকে IOError(পাইথন 2) বা BrokenPipeError(পাইথন 3) ধরতে হবে । আপনার প্রোগ্রামের উপর নির্ভর করে আপনি তাড়াতাড়ি প্রস্থান করার চেষ্টা করতে পারেন বা কেবল ব্যতিক্রম উপেক্ষা করতে পারেন:

from errno import EPIPE

try:
    broken_pipe_exception = BrokenPipeError
except NameError:  # Python 2
    broken_pipe_exception = IOError

try:
    YOUR CODE GOES HERE
except broken_pipe_exception as exc:
    if broken_pipe_exception == IOError:
        if exc.errno != EPIPE:
            raise

তবে, এটি যথেষ্ট নয়। পাইথন 3 এখনও এই জাতীয় বার্তা প্রিন্ট করতে পারে:

Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe

দুর্ভাগ্যক্রমে এই বার্তাটি থেকে মুক্তি পাওয়া সহজ নয়, তবে অবশেষে আমি http://bugs.python.org/issue11380 খুঁজে পেয়েছি যেখানে রবার্ট কলিন্স এই কাজের প্রস্তাব দেয় যে আমি একটি ডেকরেটারে পরিণত হয়েছি যার সাথে আপনি আপনার মূল ফাংশনটি গুটিয়ে রাখতে পারেন (হ্যাঁ, এটি কিছুটা ক্রেজি) ইন্ডেন্টেশন):

from functools import wraps
from sys import exit, stderr, stdout
from traceback import print_exc


def suppress_broken_pipe_msg(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except SystemExit:
            raise
        except:
            print_exc()
            exit(1)
        finally:
            try:
                stdout.flush()
            finally:
                try:
                    stdout.close()
                finally:
                    try:
                        stderr.flush()
                    finally:
                        stderr.close()
    return wrapper


@suppress_broken_pipe_msg
def main():
    YOUR CODE GOES HERE

4
এটি আমার জন্য এটি ঠিক করবে বলে মনে হয় না।
কাইল ব্রিজেনস্টাইন

ব্রুকেনপাইপ এরর বাদে এটি আমার জন্য কাজ করেছিল: সুপারপ্রেস_ব্রোকেন_পাইপ_এমএসজি ফাংশনে পাস করুন
রূপেন বি

2

আমি জানি এটি এটি করার "যথাযথ" উপায় নয়, তবে আপনি যদি ত্রুটি বার্তা থেকে মুক্তি পেতে আগ্রহী হন তবে আপনি এই চেষ্টাটি চেষ্টা করতে পারেন:

python your_python_code.py 2> /dev/null | other_command

2

এখানে শীর্ষ উত্তর ( if e.errno == errno.EPIPE:) সত্যই আমার পক্ষে কাজ করে নি। আমি পেয়েছি:

AttributeError: 'BrokenPipeError' object has no attribute 'EPIPE'

তবে, আপনার যদি যত্ন করা সমস্ত নির্দিষ্ট লেখায় ভাঙা পাইপগুলি উপেক্ষা করে থাকে তবে এটি কাজ করা উচিত। আমি মনে করি এটি সন্ধানের ফাঁদে ফেলার চেয়ে নিরাপদ:

try:
    # writing, flushing, whatever goes here
except BrokenPipeError:
    exit( 0 )

আপনার কোডটি সত্যিই সত্য কিনা, আপনি যদি ভাঙা পাইপটি আঘাত করেন তবে সত্যই সম্পন্ন হয়েছে কিনা সে সম্পর্কে আপনাকে অবশ্যই সিদ্ধান্ত নিতে হবে, তবে বেশিরভাগ উদ্দেশ্যে আমি মনে করি এটি সাধারণত সত্য হতে চলেছে। (ফাইল হ্যান্ডলগুলি ইত্যাদি বন্ধ করতে ভুলবেন না)


1

আপনার স্ক্রিপ্ট থেকে আউটপুটটির পড়ার শেষ অকাল মারা গেলে এটিও ঘটতে পারে

অর্থাত্ ওপেন.পি | অন্যান্য কম্যান্ড

যদি অন্যান্য কম্যান্ড প্রস্থান করে এবং ওপেন.পি স্টাডাউটে লেখার চেষ্টা করে

আমার একটি খারাপ গাক স্ক্রিপ্ট ছিল যা আমার সাথে এই সুন্দর করে।


4
এটা তোলে প্রক্রিয়া নল থেকে পড়া সম্পর্কে না মরণ , অগত্যা: কিছু ইউনিক্স ইউটিলিটিগুলি, উল্লেখযোগ্য হল head, নকশা, স্বাভাবিক অপারেশনের সময় ঘনিষ্ঠ নল গোড়ার দিকে, যেমন একবার তারা অনেক তথ্য হিসাবে পড়েছি তারা প্রয়োজন ছিল। বেশিরভাগ সি এল এলই কেবল তার ডিফল্ট আচরণের জন্য সিস্টেমে স্থির থাকে: নিঃশব্দে পাঠ প্রক্রিয়াটি শেষ করে এবং প্রস্থান কোডটি রিপোর্ট করে 141(যা একটি শেলের মধ্যে সহজেই স্পষ্ট হয় না, কারণ পাইপলাইনের শেষ কমান্ড সামগ্রিক প্রস্থান কোড নির্ধারণ করে)। পাইথন এর ডিফল্ট আচরণ, দুর্ভাগ্যবশত, মরতে হয় সশব্দে
mklement0

-2

বন্ধগুলি ওপেনের বিপরীতে করা উচিত।


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