Bir alt işlemde ayrı bir dosya / komut dosyası oluşturmadan veya yazmadan işlevi çalıştırmak mümkün mü?


83
import subprocess

def my_function(x):
    return x + 100

output = subprocess.Popen(my_function, 1) #I would like to pass the function object and its arguments
print output 
#desired output: 101

Yalnızca ayrı komut dosyaları kullanarak alt işlemlerin açılmasıyla ilgili belgeler buldum. İşlev nesnelerini nasıl geçireceğini veya işlev kodunu geçirmenin kolay bir yolunu bilen var mı?


1
Çoklu işlem modülünü aradığınıza inanıyorum .
Noctis Skytower

Yanıtlar:


112

Sanırım daha çok çoklu işlem modülüne benzeyen bir şey arıyorsunuz:

http://docs.python.org/library/multiprocessing.html#the-process-class

Alt işlem modülü, işlemleri başlatmak ve giriş / çıkışları ile bir şeyler yapmak içindir - işlevleri çalıştırmak için değil.

İşte multiprocessingkodunuzun bir sürümü:

from multiprocessing import Process, Queue

# must be a global function    
def my_function(q, x):
    q.put(x + 100)

if __name__ == '__main__':
    queue = Queue()
    p = Process(target=my_function, args=(queue, 1))
    p.start()
    p.join() # this blocks until the process terminates
    result = queue.get()
    print result

20
processifyDekoratörü kısayol olarak kullanabilirsiniz : gist.github.com/2311116
schlamar

3
Bunun Python yorumlayıcısını ve alt işlem için tüm ortamını klonladığını varsayıyorum?
Jens

1
İşte python 3'te çalışan ve jeneratör işlevlerini destekleyen bir işlem çatalı. gist.github.com/stuaxo/889db016e51264581b50
Stuart Axon

4
Kuyruktan önemsiz olmayan büyüklükteki verileri geçirmeniz durumunda bu kodun bir kilitlenme içerdiğini unutmayın - sürece katılmadan önce her zaman queue.get (), aksi takdirde hiçbir şey okumazken kuyruğa yazmaya çalışırken takılır.
Petr Baudis

@schlamar Arka planda bir işlevi çalıştırmak istiyorum, ancak bazı kaynak sınırlamalarım var ve işlevi istediğim kadar çalıştıramıyorum ve işlevin fazladan yürütmelerini sıraya koymak istiyorum. Bunu nasıl yapmam gerektiğine dair bir fikrin var mı? Benim sorum var . Soruma bir bakar mısınız lütfen? Herhangi bir yardım harika olur!
Amir

17

Standart Unix forksistem çağrısını olarak kullanabilirsiniz os.fork(). fork()aynı komut dosyası çalışırken yeni bir işlem yaratacaktır. Yeni süreçte 0 döndürecektir, eski süreçte ise yeni sürecin süreç kimliğini döndürecektir.

child_pid = os.fork()
if child_pid == 0:
  print "New proc"
else:
  print "Old proc"

Birden çok işlemi kullanmak için taşınabilir bir soyutlama sağlayan çoklu işlem desteği sağlayan daha yüksek seviyeli bir kitaplık için, çoklu işlem modülü vardır. IBM DeveloperWorks, Python ile Çoklu İşlem hakkında , her iki tekniğe kısa bir giriş içeren bir makale var .


Merak ediyorum; neden olumsuz oy? Cevabımda yanlış olan bir şey var mı?
Brian Campbell

Çoklu işlem, fork () etrafında daha yüksek seviyeli bir sarmalayıcı değil, çok platformlu bir çoklu işlem araç setidir (unix'te fork kullanan). Bu önemlidir, çünkü fork () çalışmazken diyelim ki Windows üzerinde çalıştığı anlamına gelir. Düzenleme: Ve olumsuz oylamanın nedeni buydu, ancak daha sonra muhtemelen buna değmeyeceğine karar verdim. Yine de geri almak için çok geç. Düzenleme2: Daha doğrusu, fork () platformlar arası olmadığında önerilmesinin nedeni buydu.
Devin Jeanpierre

3
@Devin, eğer istersen, yaptığın bir olumsuz oyu her zaman geri alabilirsin.
Alex Martelli

O zaman bunu açıklığa kavuşturmak için düzenlendi. forkTaşınabilir olmadığını açıkça belirttim ; Genelde taşınabilir olmayan cevaplar ile birlikte taşınabilir olmadıkları bilgisini vereceğim ve soru soran kişinin onlar için yeterli olup olmadığına karar vermesine izin vereceğim. Cevabımı düzenlediğim gibi, yeterince iyileştirdiğimi düşünüyorsanız, olumsuz oyu kaldırabilirsiniz; Eğer yapmazsan hiçbir kötü his olmasa da, sadece neyi yanlış yaptığımı görmek için kontrol etmek istedim.
Brian Campbell

@Alex, hayır, yapamazsınız. Belirli bir süre geçtikten sonra, bir düzenleme gerçekleşene kadar geri alamazsınız. Yeniden düşünmeden önce bu kadar zaman geçmişti, dolayısıyla "çok geç" yorum. Her neyse, dediğim gibi, buna değmeyeceğine karar vermiştim, o yüzden gitti. Ayrıca nedenlerinizi takdir ediyorum ve anlıyorum ve her iki şekilde de sert duyguların olmayacağına sevindim. : p
Devin Jeanpierre

5

Brian McKenna'nın çoklu işlemle ilgili yukarıdaki gönderisi gerçekten yararlıdır, ancak iş parçacıklı rotadan aşağı inmek istiyorsanız (işleme dayalı olanın aksine), bu örnek size başlamanızı sağlayacaktır:

import threading
import time

def blocker():
    while True:
        print "Oh, sorry, am I in the way?"
        time.sleep(1)

t = threading.Thread(name='child procs', target=blocker)
t.start()

# Prove that we passed through the blocking call
print "No, that's okay" 

Bu setDaemon(True)özelliği, ileti dizisinin hemen arka planını oluşturmak için de kullanabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.