একবার * ইউনিক্সে সম্পূর্ণ প্রক্রিয়া চলমান যন্ত্রপাতিটি বুঝতে পারলে আপনি সহজেই সহজ সমাধানটি খুঁজে পাবেন:
এই সহজ উদাহরণটি বিবেচনা করুন কীভাবে সিলেক্ট সিলেক্ট () আজকাল * নিক্সের সর্বত্রই পাওয়া যায়) ব্যবহার করে সময়সীকরণযোগ্য যোগাযোগ () মেথ তৈরি করা যায়। এটি এপল / পোল / কেকিউ দিয়েও লেখা যেতে পারে তবে সিলেক্ট করুন (সিলেক্ট) () রূপটি আপনার পক্ষে ভাল উদাহরণ হতে পারে। এবং নির্বাচনের প্রধান সীমাবদ্ধতা (গতি এবং 1024 সর্বোচ্চ এফডিএস) আপনার কাজের জন্য প্রযোজ্য নয়।
এটি * নিক্সের অধীনে কাজ করে, থ্রেড তৈরি করে না, সংকেত ব্যবহার করে না, কোনও থ্রেড (কেবলমাত্র প্রধান নয়) থেকে হাসানো যেতে পারে এবং আমার মেশিনে স্ট্রাউড থেকে 250 এমবি / এস ডেটা পড়ার জন্য আগ্রহী (i5 2.3ghz)।
যোগাযোগের শেষে stdout / stderr এ যোগদান করতে সমস্যা আছে। আপনার যদি বিশাল প্রোগ্রাম আউটপুট থাকে তবে এটি বড় মেমরির ব্যবহারের দিকে নিয়ে যেতে পারে। তবে আপনি সংক্ষিপ্ত সময়ের সাথে সংযুক্তি () কয়েকবার কল করতে পারেন।
class Popen(subprocess.Popen):
def communicate(self, input=None, timeout=None):
if timeout is None:
return subprocess.Popen.communicate(self, input)
if self.stdin:
# Flush stdio buffer, this might block if user
# has been writing to .stdin in an uncontrolled
# fashion.
self.stdin.flush()
if not input:
self.stdin.close()
read_set, write_set = [], []
stdout = stderr = None
if self.stdin and input:
write_set.append(self.stdin)
if self.stdout:
read_set.append(self.stdout)
stdout = []
if self.stderr:
read_set.append(self.stderr)
stderr = []
input_offset = 0
deadline = time.time() + timeout
while read_set or write_set:
try:
rlist, wlist, xlist = select.select(read_set, write_set, [], max(0, deadline - time.time()))
except select.error as ex:
if ex.args[0] == errno.EINTR:
continue
raise
if not (rlist or wlist):
# Just break if timeout
# Since we do not close stdout/stderr/stdin, we can call
# communicate() several times reading data by smaller pieces.
break
if self.stdin in wlist:
chunk = input[input_offset:input_offset + subprocess._PIPE_BUF]
try:
bytes_written = os.write(self.stdin.fileno(), chunk)
except OSError as ex:
if ex.errno == errno.EPIPE:
self.stdin.close()
write_set.remove(self.stdin)
else:
raise
else:
input_offset += bytes_written
if input_offset >= len(input):
self.stdin.close()
write_set.remove(self.stdin)
# Read stdout / stderr by 1024 bytes
for fn, tgt in (
(self.stdout, stdout),
(self.stderr, stderr),
):
if fn in rlist:
data = os.read(fn.fileno(), 1024)
if data == '':
fn.close()
read_set.remove(fn)
tgt.append(data)
if stdout is not None:
stdout = ''.join(stdout)
if stderr is not None:
stderr = ''.join(stderr)
return (stdout, stderr)