2016-01-29 399 views
0

我對Python非常新,我現在被某些東西卡住了。我正在使用Python 2.7。 我正試圖自動化一個我編寫python腳本的shell命令。我必須輸入一個整數值給我使用Popen.communicate(輸入='2')的shell。儘管輸入已通過,但它作爲字符串傳遞,子進程需要它作爲數值。當嘗試將其傳遞作爲像Popen.communicate一個數字小值(輸入= 2)它引發以下錯誤:Popen.communicate通過整數輸入參數

TypeError: 'int' object has no attribute '__getitem__'

所以有任何方法來發送輸入作爲數字值Δα

這裏是我使用的代碼:

import sys 
from subprocess import Popen, PIPE, STDOUT 

cmd = ["sudo", "./sbt", "project java-examples", "run"] 
proc = Popen(cmd, bufsize=4096, shell=False, stdout=PIPE, stdin=PIPE, stderr=STDOUT) 

string = proc.communicate(input='2') 
print string[0] 
proc.stdin.close() 

編輯: 對不起,我沒有在第一位置提到了這一點。 我的Java應用程序有多個主類,因此編譯器會詢問要執行哪個類,並且每次都需要輸入相同的數字,這就是爲什麼我要將它自動化的原因。當我傳遞一個字符串值時,它會拋出numberformatexception。

+0

https://docs.python.org/2/library/subprocess.html#subprocess.Popen.communicate - *「可選的輸入參數應該是一個字符串發送到子進程」*,因此不是它的不可能。這很好,因爲管道是texty,而不是Python對象,所以它需要「數字」值2而不是字符串「2」是沒有意義的。那是什麼意思?當你通過'input ='2''時會發生什麼? – TessellatingHeckler

+0

@TessellatingHeckler子流程需要一個數字輸入,而不是一個字符串輸入,所以當我傳遞一個字符串值時,它會拋出一個「無效數字:java.lang.NumberFormatException:對於輸入字符串:」「」。並且更改子進程的輸入類型不是一個選項,因爲它是由shell本身而不是子進程提示的。 – aladeen

回答

1

最後我找到了解決方案。 好解決,這是非常簡單的


當我改變

string = proc.communicate(input='2')

string = proc.communicate(input='2\n')

它工作得很好。

+0

不接受EOF作爲行尾的代碼被破壞,即如果子進程接受整個輸入的「2 \ n」,那麼它也應該接受「2」。 – jfs

0

您調用的./sbt進程需要能夠讀取字符串並將其轉換爲整數。只有Popen不能將本地Python類型發送到子進程。

另一個可能的解決方案是將數據序列化爲JSON,YAML,XML,python pickle格式等 - 選擇你的標準。然而,當你傳遞一個整數時,這看起來非常過分。

+0

更改子進程的輸入類型不是一個選項,因爲它是由shell本身而不是子進程提示的。 – aladeen

+0

我認爲你還不瞭解我們在說什麼。 stdin/stdout/stderr只是''str''(Python3:''bytes'')。這是Unix的工作原理。子進程可以將一個數字讀取爲一個字符串,然後將其轉換爲一個整數 - 這很可能。如果您引用衍生進程的代碼,我們可能會爲您提供更多幫助。 –

+0

我想運行一個java應用程序,它有多個主類。因此,它會提示「檢測到多個主類,選擇一個運行: [1] TestProducer [2] kafka.examples.SimpleConsumerDemo [3] kafka.examples.KafkaConsumerProducerDemo 」 – aladeen

0

管道是Unix中的字節流。沒有數字輸入 - 只有「字符串」輸入(沒有數字或其他 - 只有字節)。

如果您的子java進程需要一個數字作爲其ascii表示,那麼.communicate(input='2')在從子進程讀取stdin(System.in)時已經正確。如果java進程直接從控制檯讀取(System.console().readLine()),那麼stdin=PIPE將不起作用(您可能需要在此情況下提供一個pty,例如使用pexpect)。

例如,從stdin讀取的整數,並且在Java中打印它回:

#!/usr/bin/env python2 
from subprocess import Popen, PIPE 

p = Popen(['java', '-ea', 'ReadInteger'], stdin=PIPE, stdout=PIPE) 
output = p.communicate(input='2')[0] 
print 'from java {' + output.strip() + '}' 

import java.util.Scanner; 

public class ReadInteger 
{ 
    public static void main(String args[]) 
    { 
    Scanner in = new Scanner(System.in); 
    int i = in.nextInt(); 
    System.out.println("got " + i); 
    } 
} 

要經由配管傳遞到Java進程從Python進程的整數它的工作原理是(輸出是from java {got 2})。

它停止工作,如果子進程從控制檯讀取改爲:

public class ReadIntegerConsole 
{ 
    public static void main(String args[]) 
    { 
    int i = Integer.parseInt(System.console().readLine()); 
    System.out.println("got " + i); 
    } 
} 

同樣的Python腳本導致NullPointerException(和輸出from java {}),因爲System.console()爲空在這裏(標準輸入重定向)。它的工作原理,如果我們提供了一個僞終端:

#!/usr/bin/env python2 
import pexpect # $ pip install pexpect 

child = pexpect.spawn('java -ea ReadIntegerConsole') 
child.setecho(False) 
child.sendline('2') 
child.expect(pexpect.EOF) 
child.close() 
print "from java {" + child.before.strip() + "}" 

它的工作原理(輸出from java {got 2})。

+0

謝謝您的詳細解答,但恐怕它不能解決我的問題。我確切的問題是,Java編譯器找到多個主類,並詢問要執行哪一個,並且每次都必須輸入相同的選項,這就是爲什麼我試圖自動執行它。當一個字符串'2'被傳遞時,它會拋出一個數字形式的錯誤。 – aladeen

+0

@aladeen:不要在評論中提供問題信息的必要信息,而是編輯您的問題(包括完整的堆棧跟蹤)。即使您用來啓動Java程序的工具直接與控制檯一起工作,pexpect也應該可以工作。這是一個複雜的解決方案;我會嘗試傳遞一個特定的Java類名稱,例如'['java','-ea','ReadInteger']'。你應該從我的回答中理解兩件事:(1)*「沒有數字或其他任何東西 - 只有字節」*(2)[一個進程可以繞過標準輸入並直接從控制檯讀取輸入](http: //goo.gl/WsYtYk)。 – jfs