2017-06-17 169 views
6

有一個在IPython中Jupyter筆記本電腦一個有趣的選擇直接從筆記本執行命令行語句。例如:運行命令行代碼

! mkdir ... 
! python file.py 

而且 - 這個代碼可以使用os運行:

import os 
os.system('cmd command') 

,但我怎麼運行交互shell命令。例如:

!conda install package 

可能需要未來輸入([Y]/N)或文件夾的位置,但將不接受進一步的輸入。

+0

快速問題:您使用哪種操作系統 詢問?對於這個問題,我認爲很重要。顯然,如果你願意的話,你可以進入Bash shell,但是如果你在Windows上,這並沒有太大的區別。 –

+0

我想這與它們中的3個相關,但我特別感興趣的是Mac OS系統。 – Dimgold

+0

Mac可能可能有一個bash shell。我明天會研究它。 –

回答

0

我張貼此作爲一個答案。這不是一個好的答案,但我處理問題的方式是編寫一個bash腳本以便在後臺運行。我已經看過'!'運營商,它似乎沒有很多的文件。我甚至無法在Jupyter中找到它。文章:

[Safari瀏覽器本書Jupyter前身和組件的IPython] [1] https://www.safaribooksonline.com/blog/2014/02/12/using-shell-commands-effectively-ipython/

表明,這是簡單的事情之前,可能永遠應的方式。除非你想破解Jupyter Notebook的Magic Commands部分並自己修復它。

儘管如此,考慮到有一點bash編程(這很簡單,重點突出),你可以做你想做什麼,你可能會考慮這條路線。特別是如果你需要足夠的結果來使其聲譽。

如果你想看看與針對預期的響應這個答案運行bash腳本,是你在找什麼:Have bash script answer interactive prompts

0

好選項用於大多數我遇到的命令是使用非交互式ARGS 。例如。在上述情況下:

conda install package -y 

如果你絕對需要養活的提示,你可以用printf破解,例如:

printf 'y\n' | conda install package 

它支持多種輸入,您可以通過「\ n」

它們分開
1

!command語法是%system魔法的替代語法,可以找到here

正如你猜測,它調用os.systemos.system作品,有沒有簡單的方法來知道你將運行的過程是否需要用戶輸入。因此,當使用筆記本電腦或任何多進程前端時,您無法動態地爲您正在運行的程序提供輸入。 (不像在Python中調用input我們可以攔截)。

當你明確地顯示,從筆記本,我建議您閱讀the following from Jake Van Der Plas這是關於這個問題的討論最近的總結安裝軟件包的興趣,並解釋了一些這樣的併發症。您當然可以使用conda的--yes選項,但它不能保證使用conda安裝將始終有效。也

注意!commandIPython的特性,而不是一個Jupyter。

1

假設你在問交互性,你可以嘗試一些東西。

如果您想知道如何當電池的輸出端Jupyter知道:嗯,這顯然不知道,它只是轉儲任何捕獲輸出到最近最活躍的細胞:

import threading,time 
a=5 
threading.Thread(target=lambda:[print(a),time.sleep(20),print(a)]).start() 

(故意短-than-很好的例子,因爲這僅僅是側面的信息。雖然20秒的等待運行你有時間來激活另一個細胞,可能通過發出​​)

這可以被用來獲取一些輸出控制檯代碼到屏幕上,同時從主線程控制它:

import sys,threading,subprocess 

proc=subprocess.Popen('/bin/sh',stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.STDOUT) 
pout=proc.stdout 
pin=proc.stdin 

def outLoop(): 
    running=True 
    while(running): 
     line=pout.readline().decode(sys.stdout.encoding) 
     print(line,end='') 
     running='\n' in line 
    print('Finished') 

threading.Thread(target=outLoop).start() 

然後你可以isssue命令,如

pin.write(b'ls -l\n') 
pin.flush() 

pin.write(b'exit\n') 
pin.flush() 

即使b'ls\nexit\n'的作品,這就是爲什麼outLoop如此之長(一個簡單的while(proc.poll() is None) - print(...)循環將完成早於它抓住了所有的輸出。

那麼整個事情可以自動爲:

while(proc.poll() is None): 
    inp=bytearray(input('something: ')+'\n',sys.stdin.encoding) 
    if(proc.poll() is None): 
     pin.write(inp) 
     pin.flush() 

這非常適用於https://try.jupyter.org/,但顯然我不想嘗試安裝暢達包那裏,所以我不知道會發生什麼時,暢達問一個題。

幸運的是,輸入字段停留在單元格的底部(使用ls;sleep 10;ls進行測試)。不幸的是,輸入字段最後需要額外輸入才能消失(並且這已經是'很好'的方式,當它是一個簡單的while(...)-write(bytearray(input()))-flush() 3-liner,它正在退出,但有一個例外。

如果有人想嘗試在Windows操作系統上,它的工作原理與'cmd',但我建議使用sys.stdin/out.encoding硬編碼'windows-1252'相反:他們說UTF-8,但一個簡單的dir命令已經產生輸出既不是UTF-8也不ASCII (大小爲3位的組之間的非易碎空間爲0xA0字符)或者只刪除decode部分(並使用running=0xA in line