पायथन में सबप्रोसेस के साथ आउटपुट को रीडायरेक्ट कैसे करें?


97

मैं कमांड लाइन में क्या करता हूं:

cat file1 file2 file3 > myfile

मैं अजगर के साथ क्या करना चाहता हूं:

import subprocess, shlex
my_cmd = 'cat file1 file2 file3 > myfile'
args = shlex.split(my_cmd)
subprocess.call(args) # spits the output in the window i call my python program

उपप्रकार में इस तरह के आदेश को निष्पादित करने से आपको कोई आउटपुट नहीं मिलेगा। हो सकता है कि आप इसे बिना चलाना चाहें > myfile redirecting output from cat file1 file2 file3 in python?
पोल्टो

@PoltoS मैं कुछ फ़ाइलों में शामिल होना चाहता हूँ और फिर परिणामी फ़ाइल को संसाधित करना चाहता हूँ। मैंने सोचा कि बिल्ली का उपयोग करना सबसे आसान विकल्प था। क्या इसे करने का एक बेहतर / पैथोनिक तरीका है?
catatemypythoncode

os.sendfile()
-बेड

1
मुझे लगता है कि आउटपुट पुनर्निर्देशन ('>' या '>>') उपप्रकार में काम नहीं करता है। बंद करें (कम से कम पायथन 2.7 में) (शेल = ट्रू मोड में) इस उदाहरण में, जैसा कि अन्य लोग बताते हैं, आप आसपास काम कर सकते हैं यह पुनर्निर्देशन का उपयोग नहीं करके, लेकिन अन्य मामलों में पुनर्निर्देशन उपयोगी है। यदि उप-प्रक्रम में पुनर्निर्देशन या पाइपिंग का समर्थन नहीं किया जाता है। पपेन का दस्तावेजीकरण किया जाना चाहिए (और / या os.system () को तब तक नहीं हटाया जाना चाहिए जब तक कि यह तय न हो जाए)
Ribo

जवाबों:


20

अद्यतन: os.system को हतोत्साहित किया जाता है, यद्यपि अभी भी पायथन 3 में उपलब्ध है।


उपयोग करें os.system:

os.system(my_cmd)

यदि आप वास्तव में उपप्रकार का उपयोग करना चाहते हैं, तो यहां समाधान (ज्यादातर उपप्रकार के लिए दस्तावेज से उठा लिया गया है):

p = subprocess.Popen(my_cmd, shell=True)
os.waitpid(p.pid, 0)

OTOH, आप सिस्टम कॉल से पूरी तरह से बच सकते हैं:

import shutil

with open('myfile', 'w') as outfile:
    for infile in ('file1', 'file2', 'file3'):
        shutil.copyfileobj(open(infile), outfile)

1
यह काम करता है, लेकिन फिर मैं आपसे पूछता हूं: यदि उप.प्रणाली पुस्तकालय की बात है तो ओएस.सिस्टम पहले से ही काम कर रहा है? मुझे लग रहा है कि मुझे इसके बजाय सबप्रोसेस का उपयोग करना चाहिए था क्योंकि यह एक पुस्तकालय है जो इस कार्य के लिए समर्पित है, हालाँकि जब से मैं यह सिर्फ अपने लिए कर रहा हूं मैं इस बार os.system का उपयोग करके ठीक हो जाऊंगा।
catatemypythoncode

सबप्रोसेस पुस्तकालय की तुलना में बहुत अधिक लचीला है os.system, और os.systemसटीक रूप से मॉडल कर सकता है , लेकिन इसके साथ काम करना भी अधिक जटिल है।
मार्सेलो कैंटोस

13
os.systemपहले आया था subprocess। पूर्व एक विरासत एपीआई है जिसे बाद में प्रतिस्थापित करने का इरादा है।
संता

5
@ catatemypythoncode: आपको उपयोग os.system()या नहीं करना चाहिए shell=True। एक उपप्रकार के आउटपुट को पुनर्निर्देशित करने के लिए, रेयान थॉम्पसन के उत्तरstdout में दिखाए गए अनुसार पैरामीटर का उपयोग करें । यद्यपि आपको अपने मामले में एक उपप्रकार ( ) की आवश्यकता नहीं है , आप शुद्ध पायथन का उपयोग करके फ़ाइलों को सुरक्षित कर सकते हैं। cat
JFS


271

में अजगर 3.5+ उत्पादन रीडायरेक्ट करने के लिए, बस के लिए एक खुली फ़ाइल संभाल पारित stdoutकरने के लिए तर्क subprocess.run:

# Use a list of args instead of a string
input_files = ['file1', 'file2', 'file3']
my_cmd = ['cat'] + input_files
with open('myfile', "w") as outfile:
    subprocess.run(my_cmd, stdout=outfile)

जैसा कि दूसरों ने बताया है, catइस उद्देश्य के लिए बाहरी आदेश का उपयोग पूरी तरह से बाहरी है।


9
पाइथन से खोल का उपयोग करते समय पाइपिंग के सामान्य प्रश्न का उत्तर होना चाहिए
कौशिक घोष

46
यह सही उत्तर है, सही के रूप में चिह्नित नहीं है।
जस्टिन ब्लेक

7
पायथन 3.5+ उपयोग के लिए subprocess.run(my_cmd, stdout=outfile)जो प्रतिस्थापित कर रहा हैsubprocess.call(...)
ऑस्टिन येट्स

1
ध्यान दें, यह कस्टम फ़ाइल ऑब्जेक्ट्स के साथ काम नहीं करता है, अगर उनके पास एक फ़िलीनो फ़ील्ड नहीं है (यदि वे वास्तविक फ़ाइल नहीं हैं।)
Eliezer Miron

1
जैसा कि पायथन <3.5 अब के रूप में पदावनत है, मैंने आपकी टिप्पणी के साथ उत्तर को अपडेट किया है, @AustinYates।
ग्रेग डबकी

5

@PoltoS मैं कुछ फ़ाइलों में शामिल होना चाहता हूँ और फिर परिणामी फ़ाइल को संसाधित करना चाहता हूँ। मैंने सोचा कि बिल्ली का उपयोग करना सबसे आसान विकल्प था। क्या इसे करने का एक बेहतर / पैथोनिक तरीका है?

बेशक:

with open('myfile', 'w') as outfile:
    for infilename in ['file1', 'file2', 'file3']:
        with open(infilename) as infile:
            outfile.write(infile.read())

1
size = 'ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1:nokey=1 dump.mp4 > file'
proc = subprocess.Popen(shlex.split(size), shell=True)
time.sleep(1)
proc.terminate() #proc.kill() modify it by a suggestion
size = ""
with open('file', 'r') as infile:
    for line in infile.readlines():
        size += line.strip()

print(size)
os.remove('file')

जब आप उपप्रकार का उपयोग करते हैं , तो प्रक्रिया को मार दिया जाना चाहिए। यह एक उदाहरण है। यदि आप इस प्रक्रिया को नहीं मारते हैं, तो फ़ाइल खाली हो जाएगी और आप कुछ भी नहीं पढ़ सकते हैं। यह विंडोज पर चल सकता है मैं यह सुनिश्चित कर सकता हूं कि यह नहीं है। यूनिक्स पर चलाएं।


1
यह एक बुरा कोड उदाहरण है (यह यूनिक्स पर काम नहीं करेगा; यह बुरी प्रथाओं को प्रदर्शित करता है ) for line in .readlines():, s +=और proc.kill()सामान्य रूप से सूचना हानि हो सकती है (यह उपप्रकार को शान से समाप्त करने की अनुमति नहीं देता है (यूनिक्स पर) - अप्रभावित सामग्री खो जाती है )। वैसे भी, टिप्पणी के रूप में बफरिंग के बारे में नोट अधिक उपयुक्त है।
JFS

मैं इसे विंडोज पर चलाता हूं ठीक है (क्योंकि मारना विंडोज पर समाप्त होने के बराबर है)। यूनिक्स पर हो सकता है कि आप proc.terminate () का उपयोग करें। @ JF सेबस्टियन I ने अपने कंप्यूटर पर यूनिक्स सिस्टम को नहीं बनाया है।
wyx

आप Windows पर कर रहे हैं तो ड्रॉप shlex.split(), ड्रॉप shell=True, ड्रॉप >file, ड्रॉप open(), आदि और उपयोग stdout=PIPE, Timer(1, proc.terminate).start(); output = proc.communicate()[0]बजाय। यहाँ पूरा उदाहरण है । अधिक समाधान: बिना लटके पायथन में पढ़ने की प्रक्रिया का उत्पादन बंद कर दें? नोट: इस प्रश्न में कोई आवश्यकता नहीं है कि आपको बच्चे की प्रक्रिया को मैन्युअल रूप से समाप्त करने की आवश्यकता है - आप अन्य मुद्दों को संबोधित कर सकते हैं उदाहरण के लिए, एक प्रक्रिया अलग तरह से व्यवहार कर सकती है यदि उसका स्टडीआउट एक ट्टी है, लेकिन यह ऑफ-टॉपिक है।
jfs

0

एक दिलचस्प मामला यह होगा कि किसी फाइल को उसी तरह से जोड़कर अपडेट किया जाए। तब किसी को इस प्रक्रिया में एक नई फ़ाइल नहीं बनानी होगी। यह उस स्थिति में विशेष रूप से उपयोगी है जहां एक बड़ी फ़ाइल को संलग्न करने की आवश्यकता होती है। यहां एक संभावना है कि अजगर से सीधे मंदिर कमांड लाइन का उपयोग किया जाए।

import subprocess32 as sub

with open("A.csv","a") as f:
    f.flush()
    sub.Popen(["cat","temp.csv"],stdout=f)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.