2017-06-17 177 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