2015-08-19 29 views
2

我想在GNU並行Python中編寫一個包裝來並行運行一個命令,但似乎誤解了GNU並行工作方式,系統管道和/或python子進程管道。Python管道使用GNU並行

本質上我正在尋找使用GNU並行來處理分裂輸入文件,然後在多個主機上並行運行另一個命令。

我可以研究一些純Python的方式來做到這一點在未來,但它似乎應該很容易實現使用GNU並行。

t.py

#!/usr/bin/env python 

import sys 

print 
print sys.stdin.read() 
print 

p.py

from subprocess import * 
import os 
from os.path import * 

args = ['--block', '10', '--recstart', '">"', '--sshlogin', '3/:', '--pipe', './t.py'] 

infile = 'test.fa' 

fh = open('test.fa','w') 
fh.write('''>M02261:11:000000000-ADWJ7:1:1101:16207:1115 1:N:0:1 
CAGCTACTCGGGGAATCCTTGTTGCTGAGCTCTTCCCTTTTCGCTCGCAGCTACTCGGGGAATCCTTGTTGCTGAGCTCTTCCCTTTTCGCTCGCAGCTACTCGGGGAATCCTTGTTGCTGAGCTCTTCCCTTTTCGCTCGCAGCTACTCGGGGAATCCTTGTTGCTGAGCTCTTCCCTTT 
>M02261:11:000000000-ADWJ7:1:1101:21410:1136 1:N:0:1 
ATAGTAGATAGGGACATAGGGAATCTCGTTAATCCATTCATGCGCGTCACTAATTAGATGACGAGGCATTTGGCTACCTTAAGAGAGTCATAGTTACTCCCGCCGTTTACC 
>M02261:11:000000000-ADWJ7:1:1101:13828:1155 1:N:0:1 
GGTTTAGAGTCTCTAGTCGATAGATCAATGTAGGTAAGGGAAGTCGGCAAATTAGATCCGTAACTTCGGGATAAGGATTGGCTCTGAAGGCTGGGATGACTCGGGCTCTGGTGCCTTCGCGGGTGCTTTGCCTCAACGCGCGCCGGCCGGCTCGGGTGGTTTGCGCCGCCTGTGGTCGCGTCGGCCGCTGCAGTCATCAATAAACAGCCAATTCAGAACTGGCACGGCTGAGGGAATCCGACGGTCTAATTAAAACAAAGCATTGTGATGGACTCCGCAGGTGTTGACACAATGTGATTTT 
>M02261:11:000000000-ADWJ7:1:1101:14120:1159 1:N:0:1 
GAGTAGCTGCGAGCGAAAAGGGAAGAGCTCAAGGGGAGGAAAAGAAACTAACAAGGATTCCCCGAGTAGCTGCGAGCGAAAAGGGAAGCGCCCAAGGGGGGCAACAGGAACTAACAAGAATTCGCCGACTAGCTGCGACCTGAAAAGGAAAAACCCAAGGGGAGGAAAAGAAACTAACAAGGATTCCCCGAGTAGCTGCGAGCAGAAAAGGAAAAGCACAAGAGGAGGAAACGACACTAATAAGACTTCCCATACAAGCGGCGAGCAAAACAGCACGAGCCCAACGGCGAGAAAAGCAAAA 
>M02261:11:000000000-ADWJ7:1:1101:8638:1172 1:N:0:1 
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN 
''') 
fh.close() 

# Call 1 
Popen(['parallel']+args, stdin=open(infile,'rb',0), stdout=open('output','w')).wait() 

# Call 2 
_cat = Popen(['cat', infile], stdout=PIPE) 
Popen(['parallel']+args, stdin=_cat.stdout, stdout=open('output2','w')).wait() 

# Call 3 
Popen('cat '+infile+' | parallel ' + ' '.join(args), shell=True, stdout=open('output3','w')).wait() 

呼叫1和呼叫2產生相同的輸出,同時呼叫3產生輸出我期望其中輸入文件被分割並在記錄之間包含空行。

我更好奇的差異呼叫1,2之間有什麼和Call 3.

+0

你打開使用非GNU並行的東西?如果你已經在Python [織物](http://www.fabfile.org/)工作,可能是一種更簡單的方式來推動你的數據。其他方法包括使用[IPython.parallel](http://ipython.org/ipython-doc/dev/parallel/)與SSH集羣管理或[celery](http://www.celeryproject.org/)a分佈式任務隊列 –

+0

腳本將最終運行在PBS或SGE作業中,因此織物可能效果最好。就目前而言,我只是對調用中的差異感興趣。 – Necrolyte2

+0

肯定看看IPython,它已經包含PBS和SGE的代碼 –

回答

1

TL; DR不要引用">"shell=False

如果使用shell=True,則可以使用shell的所有功能,例如通配符,I/O重定向等。您需要引用任何需要從shell中轉義出來的內容。您可以將整個命令行作爲單個字符串傳遞,並且shell將解析它。

unsafe = subprocess.Popen('echo `date` "my files" * >output', shell=True) 

隨着shell=False,你有幕後沒有「祕密」的副作用,並沒有殼的設施提供給您。所以你需要關注Python方面的globbing,重定向等。在加號賬戶中,您保存了一個(可能很重要的)額外流程,您擁有更多的控制權,並且您不需要(也確實不必)引用涉及shell時必須引用的內容。總之,這也更安全,因爲你可以清楚地看到你在做什麼。

cmd = ['echo'] 
cmd.append(datestamp()) 
cmd.append['my files'] # notice absence of shell quotes around string 
cmd.extend(glob('*')) 
safer = subprocess.Popen(cmd, shell=False, stdout=open('output', 'w+')) 

(這還是略有不同,因爲有現代化的炮彈,echo是內置的,而現在,我們將執行外部程序/bin/echo或任何可執行文件使用該名稱是第一位在PATH。)

現在,回到您的示例,您的args中的問題是,您正在引用文字">"作爲記錄分隔符。當涉及到一個shell時,一個沒有引號的右代理會調用重定向,所以爲了將其指定爲一個字符串,它必須被轉義或引用。但是當圖片中沒有外殼時,沒有任何處理(或需要)這些引用的內容,所以要傳遞一個文字>參數,只需簡單地傳遞它即可。

因爲這樣,你的電話#1絕對看起來像要走的路。 (儘管我並不完全相信爲在Perl中實現的shell命令編寫一個Python包裝是理智的,但我懷疑直接在Python中並行處理一堆並行子進程不會更復雜。)