পাইথনে একটি ব্যাকগ্রাউন্ড প্রক্রিয়া কীভাবে শুরু করবেন?


294

আমি অনেক বেশি পঠনযোগ্য অজগর সংস্করণে একটি শেল স্ক্রিপ্ট পোর্ট করার চেষ্টা করছি। আসল শেল স্ক্রিপ্টটি "&" দিয়ে ব্যাকগ্রাউন্ডে বেশ কয়েকটি প্রক্রিয়া (ইউটিলিটিস, মনিটর ইত্যাদি) শুরু করে। অজগরে আমি কীভাবে একই প্রভাব অর্জন করতে পারি? অজগর স্ক্রিপ্টগুলি সম্পূর্ণ হলে আমি এই প্রক্রিয়াগুলি না মরতে চাই। আমি নিশ্চিত যে এটি কোনওভাবে ডেমনের ধারণার সাথে সম্পর্কিত, তবে কীভাবে সহজে এটি করা যায় তা আমি খুঁজে পাইনি।



1
হাই আর্টেম অনুগ্রহ করে ড্যানের উত্তর গ্রহণ করুন কারণ (১) আরও ভোট, (২) subprocess.Popen()২০১০ সাল থেকে নতুন প্রস্তাবিত উপায় (আমরা এখন ২০১৫ সালে আছি) এবং (৩) এখানে নকল করা প্রশ্নটি পুনঃনির্দেশিত করার বিষয়ে একটি স্বীকৃত উত্তরও রয়েছে subprocess.Popen()। চিয়ার্স :-)
অলিব্রে

1
@ অলিব্রে আসলে উত্তরটি উপযুক্ত কম শেবাংয়ের subprocess.Popen("<command>")নেতৃত্বে <কম্যান্ড> ফাইলের সাথে থাকা উচিত । ব্যাশ এবং পাইথন স্ক্রিপ্টগুলি সহ আমার (ডেবিয়ান) জন্য নিখুঁতভাবে কাজ করে, ছদ্মবেশীভাবে shellএর মূল প্রক্রিয়াটি বেঁচে থাকে। stdoutপিতামাতার চেয়ে একই টার্মিনালে যায়। সুতরাং এটি অনেকটা &শেলের মতোই কাজ করে যা অপের অনুরোধ ছিল। তবে জাহান্নাম, সমস্ত পরীক্ষা খুব জটিল হয়ে ওঠে যখন একটি সামান্য পরীক্ষা করে দেখানো হয় যে এটি কোনও সময়ই নেই;)
ফ্ল্যাশবিয়ার

পটভূমির জন্য হয়তো আরো দেখুন stackoverflow.com/a/51950538/874188
tripleee

উত্তর:


84

দ্রষ্টব্য : এই উত্তরটি ২০০৯-এ পোস্ট করার সময়কার চেয়ে কম বর্তমান subprocessother অন্যান্য উত্তরে প্রদর্শিত মডিউলটি এখন ডক্সে সুপারিশ করা হচ্ছে

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


আপনি যদি নিজের প্রক্রিয়াটি পটভূমিতে শুরু করতে চান তবে আপনি system()নিজের শেল স্ক্রিপ্টটি একইভাবে ব্যবহার করতে এবং কল করতে পারেন বা আপনি spawnএটি করতে পারেন:

import os
os.spawnl(os.P_DETACH, 'some_long_running_command')

(বা, বিকল্পভাবে, আপনি কম পোর্টেবল os.P_NOWAITপতাকা চেষ্টা করতে পারেন )।

দেখুন ডকুমেন্টেশন এখানে


8
মন্তব্য: এক্সিকিউটেবলের জন্য আপনাকে অবশ্যই পুরো পথ নির্দিষ্ট করতে হবে। এই ফাংশনটি PATH ভেরিয়েবল ব্যবহার করবে না এবং যে রূপটি এটি ব্যবহার করে তা উইন্ডোজ এর অধীন উপলব্ধ নয়।
সোরিন

36
সরাসরি আমার জন্য অজগর ক্রাশ।
পাবলো

29
os.P_NETAIT এর সাথে os.P_DETach প্রতিস্থাপন করা হয়েছে।
নিজে 19

7
যে লোকেরা ব্যবহারের পরামর্শ দিচ্ছেন তারা subprocessকীভাবে একটি প্রক্রিয়া আলাদা করতে আমাদের একটি ইঙ্গিত দিতে পারেন subprocess?
রাকস্লাইস

3
আমি কীভাবে পাইথন স্ক্রিপ্টটি ব্যবহার করতে পারি (সংযুক্তি.পি বলুন) একটি ব্যাকগ্রাউন্ড প্রক্রিয়া সন্ধান করতে এবং এর আইও পুনর্নির্দেশ করতে যাতে সংযুক্তিপি পটভূমিতে কিছু_লং_রুনিং_প্রোগ থেকে / লিখতে পারে?
raof01

375

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

আপনার ক্ষেত্রে উদাহরণ:

import subprocess
subprocess.Popen(["rm","-r","some.file"])

এটি rm -r somefileপটভূমিতে চলবে । মনে রাখবেন যে .communicate()অবজেক্টটি থেকে ফিরে Popenআসাটি সম্পূর্ণ হওয়া অবধি বন্ধ হয়ে যাবে, তাই আপনি যদি এটি ব্যাকগ্রাউন্ডে চালাতে চান তবে তা করবেন না:

import subprocess
ls_output=subprocess.Popen(["sleep", "30"])
ls_output.communicate()  # Will block for 30 seconds

ডকুমেন্টেশন এখানে দেখুন

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


7
@ ড্যান: ব্যাকগ্রাউন্ডে চলার পরে আমি কীভাবে এটি মারব? আমি এটি কিছুক্ষণ চালাতে চাই (এটি একটি ডিমন যা আমি ইন্টারঅ্যাক্ট করি) এবং এটি শেষ হয়ে গেলে এটি মেরে ফেলতে চাই। দস্তাবেজগুলি সহায়ক নয় ...
হুয়ান

1
@ ড্যান তবে তার জন্য আমার পিআইডি জানতে হবে না? ক্রিয়াকলাপ নিরীক্ষক / কার্য পরিচালক কোনও বিকল্প নয় (প্রোগ্রামিয়ালি ঘটতে হবে)।
জুয়ান

5
ঠিক আছে সুতরাং যখন আপনি পপেন () এর ফলাফলের স্ট্যান্ডে লিখতে চান তখন আপনি কীভাবে প্রক্রিয়াটিকে পটভূমিতে জোর করবেন?
মাইকেল

2
@ জেফাসেবাস্টিয়ান: আমি এটিকে "কীভাবে একটি স্বতন্ত্র প্রক্রিয়া তৈরি করতে পারি যা বর্তমান প্রোগ্রামটির সম্পাদন বন্ধ করে না" বলে ব্যাখ্যা করেছি। এটিকে আরও স্পষ্ট করার জন্য আপনি কীভাবে এটি সম্পাদনা করার পরামর্শ দিচ্ছেন?
ড্যান

1
@ ড্যান: সঠিক উত্তরটি হ'ল: Popen()মূল থ্রেডটি ব্লক করা এড়াতে ব্যবহার করুন এবং আপনার যদি ডেমন প্রয়োজন হয় তবে একটি সংজ্ঞায়িত ডেমনকে কীভাবে আচরণ করা উচিত তা বুঝতে python-daemonপ্যাকেজটি দেখুন । আপনার উত্তর ঠিক আছে যদি আপনি সাবপ্রসেসের ডক্সের লিঙ্কটি বাদ দিয়ে "তবে সাবধান হন" দিয়ে শুরু করা সমস্ত কিছু সরিয়ে ফেলেন।
jfs

47

আপনি সম্ভবত "পাইথনে একটি বাহ্যিক কমান্ড কল করবেন " এর উত্তর চান

সবচেয়ে সহজ পদ্ধতির হ'ল os.systemফাংশনটি ব্যবহার করা , যেমন:

import os
os.system("some_command &")

মূলত, আপনি systemফাংশনে যা যা যাবেন তেমন কার্যকর হবে যেমন আপনি এটি কোনও স্ক্রিপ্টের শেলের কাছে দিয়ে গেছেন।


9
আইএমএইচও, পাইথন স্ক্রিপ্টগুলি সাধারণত ক্রস-প্ল্যাটফর্ম হিসাবে লেখা হয় এবং যদি সেখানে সাধারণ ক্রস-প্ল্যাটফর্ম সমাধান উপস্থিত থাকে তবে এটির সাথে আঁকানো আরও ভাল। ভবিষ্যতে আপনাকে অন্য প্ল্যাটফর্মের সাথে কাজ করতে হবে কিনা তা কখনই জানেন না :) বা অন্য কোনও ব্যক্তি যদি আপনার স্ক্রিপ্টটিকে তার প্ল্যাটফর্মে স্থানান্তর করতে চান।
d9k

7
এই আদেশটি সমকালীন (যেমন এটি সর্বদা শুরু হওয়া প্রক্রিয়াটি সমাপ্তির জন্য অপেক্ষা করে)।
tav

@ d9k os.sstm কি বহনযোগ্য নয়?
lucid_dreamer

1
@ d9k পটভূমিতে ইতিমধ্যে আপনাকে পজিক্স-ল্যান্ডে অবস্থান করে এমন কিছু চালানোর পছন্দ নয়? আপনি উইন্ডোজে কি করবেন? সেবা হিসাবে চালাবেন?
lucid_dreamer

নির্দিষ্ট ফোল্ডার থেকে কমান্ড চালানোর দরকার হলে আমি কীভাবে এটি ব্যবহার করতে পারি?
এমআরবোট

29

আমি এটি এখানে পেয়েছি :

উইন্ডোজগুলিতে (উইন এক্সপি), পিতা-মাতার প্রক্রিয়া শেষ না হওয়া অবধি longtask.pyতার কাজ শেষ হবে না । আপনি সিজিআই-স্ক্রিপ্টে যা চান তা নয়। পাইথনের সাথে সমস্যাটি নির্দিষ্ট নয়, পিএইচপি সম্প্রদায়ে সমস্যাগুলি একই রকম।

সমাধানটি হ'ল উইন এপিআই-তে অন্তর্নিহিত DETACHED_PROCESS কার্যটিতে প্রক্রিয়া তৈরির পতাকাটি প্রেরণ করা CreateProcess। আপনি যদি পাইউইন 32 ইনস্টল করেছেন বলে মনে হয় আপনি উইন 32 প্রসেস মডিউল থেকে পতাকাটি আমদানি করতে পারেন, অন্যথায় আপনার নিজেরাই এটি সংজ্ঞায়িত করা উচিত:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

6
প্রক্রিয়া আইডিটি কীভাবে ধরে রাখতে হয় তা দেখানোর জন্য +1। এবং যে কেউ প্রক্রিয়া ID সাথে পরে প্রোগ্রাম হত্যা করতে চাইলে: stackoverflow.com/questions/17856928/...
iChux

1
এটি কেবল উইন্ডোজ বলে মনে হচ্ছে
অড্রিয়াস মেসকাউস্কাস

24

সাথে ব্যবহার subprocess.Popen()করুনclose_fds=True পরামিতি, যা উত্পন্ন হওয়া subprocess পাইথন থেকে বিচু্যত করতে দেবে নিজেই প্রক্রিয়া ও পাইথন প্রস্থানের পরও চলমান অবিরত।

https://gist.github.com/yinjimmy/d6ad0742d03d54518e9f

import os, time, sys, subprocess

if len(sys.argv) == 2:
    time.sleep(5)
    print 'track end'
    if sys.platform == 'darwin':
        subprocess.Popen(['say', 'hello'])
else:
    print 'main begin'
    subprocess.Popen(['python', os.path.realpath(__file__), '0'], close_fds=True)
    print 'main end'

1
উইন্ডোজগুলিতে, এটি বিচ্ছিন্ন না হয়ে ক্রিয়েশনফ্ল্যাজগুলি প্যারামিটারের কাজগুলি ব্যবহার করে
স্মার্টমনোজ

3
এই সমাধানটি লিনাক্স-এ জ্যাম্বি হিসাবে একটি উপ-প্রসেস ছেড়ে যায়।
টাইটানফাইটার

: @TitanFighter এই সেট SIGCHLD SIG_IGN দ্বারা এড়ানোর হতে পারে stackoverflow.com/questions/16807603/...
sailfish009

ধন্যবাদ @ জিমি আপনার উত্তর হ'ল কেবলমাত্র সমাধান আমার জন্য কাজ করে।
sailfish009

12

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

try:
    pid = os.fork()
except OSError, e:
    ## some debug output
    sys.exit(1)
if pid == 0:
    ## eventually use os.putenv(..) to set environment variables
    ## os.execv strips of args[0] for the arguments
    os.execv(args[0], args)

2
os.fork()সত্যিই দরকারী, তবে এটি কেবল * নিক্সে উপলব্ধ থাকার একটি উল্লেখযোগ্য ডাউনসাইড রয়েছে।
ইভান ফসমার্ক

Os.fork এর একমাত্র সমস্যাটি এটি win32 নির্দিষ্ট।
jkp

এই পদ্ধতির সম্পর্কে আরও বিশদ: পাইথন পথে ডেমন তৈরি করা
আমির আলী আকবরী

আপনি এর সাথে একইরকম প্রভাবও পৌঁছাতে পারবেন threading: stackoverflow.com/a/53751896/895245 আমার ধারণা এটি উইন্ডোজে কাজ করতে পারে।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件 法轮功

9

উভয় ক্যাপচার আউটপুট এবং সাথে ব্যাকগ্রাউন্ডে চালানো threading

এই উত্তরে উল্লিখিত হিসাবে , আপনি যদি আউটপুটটি ক্যাপচার করেন stdout=এবং তারপরে চেষ্টা করেন read()তবে প্রক্রিয়াটি অবরুদ্ধ হয়।

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

threadingমডিউল আমাদের যে কাজ করতে পারেন।

প্রথমত, এই প্রশ্নে কীভাবে আউটপুট পুনঃনির্দেশ অংশটি করা যায় তা একবার দেখুন: পাইথন পপেন: একসাথে স্টাডাউট এবং লগ ফাইলটিতে লিখুন

তারপর:

main.py

#!/usr/bin/env python3

import os
import subprocess
import sys
import threading

def output_reader(proc, file):
    while True:
        byte = proc.stdout.read(1)
        if byte:
            sys.stdout.buffer.write(byte)
            sys.stdout.flush()
            file.buffer.write(byte)
        else:
            break

with subprocess.Popen(['./sleep.py', '0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc1, \
     subprocess.Popen(['./sleep.py', '10'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc2, \
     open('log1.log', 'w') as file1, \
     open('log2.log', 'w') as file2:
    t1 = threading.Thread(target=output_reader, args=(proc1, file1))
    t2 = threading.Thread(target=output_reader, args=(proc2, file2))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

sleep.py

#!/usr/bin/env python3

import sys
import time

for i in range(4):
    print(i + int(sys.argv[1]))
    sys.stdout.flush()
    time.sleep(0.5)

দৌড়ানোর পরে:

./main.py

স্টাডাউট প্রতি দুটি লাইনের জন্য প্রতি 0.5 সেকেন্ডে আপডেট হবে:

0
10
1
11
2
12
3
13

এবং প্রতিটি লগ ফাইল একটি প্রদত্ত প্রক্রিয়া জন্য সংশ্লিষ্ট লগ থাকে।

দ্বারা অনুপ্রাণিত: https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/

উবুন্টু 18.04, পাইথন 3.6.7 এ পরীক্ষিত।

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