Apa perbedaan antara subproses Popen dan panggilan (bagaimana saya bisa menggunakannya)?

178

Saya ingin memanggil program eksternal dari Python. Saya telah menggunakan keduanya Popen()dan call()untuk melakukan itu.

Apa perbedaan keduanya?

Tujuan spesifik saya adalah menjalankan perintah berikut dari Python. Saya tidak yakin bagaimana pengalihan bekerja.

./my_script.sh > output

Saya membaca dokumentasi dan mengatakan itu call()adalah fungsi kenyamanan atau fungsi pintas. Apakah kita kehilangan daya dengan menggunakan call()alih-alih Popen()?

Varunl
sumber
Bagian mana dari dokumentasi yang membuat Anda bingung? Definisi call()tampaknya sangat jelas. Bisakah Anda memberikan penawaran atau tautan sehingga kami tahu apa yang harus difokuskan dalam jawaban?
S.Lott

Jawaban:

265

Ada dua cara untuk melakukan pengalihan. Keduanya berlaku untuk subprocess.Popenatau subprocess.call.

  1. Tetapkan argumen kata kunci shell = Trueatau executable = /path/to/the/shelldan tentukan perintah seperti yang Anda miliki di sana.

  2. Karena Anda hanya mengarahkan output ke file, atur argumen kata kunci

    stdout = an_open_writeable_file_object

    di mana objek menunjuk ke outputfile.

subprocess.Popenlebih umum daripada subprocess.call.

Popentidak memblokir, memungkinkan Anda untuk berinteraksi dengan proses saat sedang berjalan, atau melanjutkan dengan hal lain di program Python Anda. Panggilan untuk Popenmengembalikan Popenobjek.

call tidak menghalangi. Meskipun mendukung semua argumen yang sama dengan Popenkonstruktor, sehingga Anda masih dapat mengatur output proses, variabel lingkungan, dll., Skrip Anda menunggu program selesai, dan callmengembalikan kode yang mewakili status keluar proses.

returncode = call(*args, **kwargs) 

pada dasarnya sama dengan menelepon

returncode = Popen(*args, **kwargs).wait()

callhanyalah fungsi kenyamanan. Implementasinya di CPython ada di subprocess.py :

def call(*popenargs, timeout=None, **kwargs):
    """Run command with arguments.  Wait for command to complete or
    timeout, then return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

Seperti yang Anda lihat, ini adalah pembungkus tipis Popen.

agf
sumber
17
Pada dasarnya, Popen dan Call adalah fungsi asinkron dan Sinkron yang masing-masing digunakan menjalankan perintah Linux.
user3016020
1
Apa keuntungan menggunakan popen? Tidakkah aman menunggu sampai program yang dipanggil selesai terlebih dahulu?
Tom
4
@ Tom Sering tidak. Bagaimana jika Anda ingin membaca beberapa output, kemudian mengirim lebih banyak input ke program, membaca lebih banyak output yang dihasilkan dari input itu, ulangi?
agf
@ user3016020 Saya menganggap ini juga berlaku untuk perintah Windows? Baik?
domih
7

Jawaban lainnya sangat lengkap, tetapi ini adalah aturan praktis:

  • call sedang memblokir:

    call('notepad.exe')
    print('hello')  # only executed when notepad is closed
  • Popen tidak memblokir:

    Popen('notepad.exe')
    print('hello')  # immediately executed
Basj
sumber