Ipython Jupyter Notebook中有一个有趣的选项,可以直接从笔记本中执行命令行语句。例如:
! mkdir ...
! python file.py
此代码还可以使用os
运行。import os
os.system('cmd command')
但是如何运行交互式的shell命令呢?例如:
!conda install package
可能需要未来的输入 ([Y]/N
) 或文件夹位置,但不会接受进一步的输入。
Ipython Jupyter Notebook中有一个有趣的选项,可以直接从笔记本中执行命令行语句。例如:
! mkdir ...
! python file.py
此代码还可以使用os
运行。import os
os.system('cmd command')
但是如何运行交互式的shell命令呢?例如:
!conda install package
可能需要未来的输入 ([Y]/N
) 或文件夹位置,但不会接受进一步的输入。
!command
语法是%system
魔术的另一种语法,其文档可以在这里找到。
正如你所猜测的那样,它调用了os.system
,只要os.system
工作正常,就没有简单的方法可以知道将要运行的进程是否需要用户输入。因此,在使用笔记本电脑或任何多进程前端时,您无法动态地向正在运行的程序提供输入(与Python中调用input
不同,我们可以拦截)。
由于您明确表达了从笔记本安装软件包的兴趣,因此我建议阅读来自Jake Van Der Plas的以下内容,它总结了对该主题的最近讨论,并解释了其中的一些复杂性。当然,您也可以选择conda的--yes
选项,但这并不能保证使用conda安装始终有效。
请注意,!command
是一个IPython功能,而不是Jupyter功能。
import threading,time
a=5
threading.Thread(target=lambda:[print(a),time.sleep(20),print(a)]).start()
< p >(这只是附加信息,意在简化示例)当20秒等待运行时,您有时间通过发出a=6
来激活另一个单元格。
这可用于将某些控制台代码的输出显示在屏幕上,同时从主线程进行控制:
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()
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/上运行良好,但我显然不想在那里尝试安装conda包,所以当conda询问时我不知道会发生什么。
一个幸运的事情是输入字段停留在单元格底部(使用ls; sleep 10; ls
进行测试)。不幸的是,输入字段需要在末尾添加额外的条目才能消失(如果它只是简单的while(...)
-write(bytearray(input()))
-flush()
3行代码,就无法成功退出)。
如果有人想在Windows上尝试这个,请使用'cmd'
,但我建议硬编码'windows-1252'
而不是sys.stdin/out.encoding
:虽然他们说是UTF-8,但仅仅执行一个dir
命令就已经产生了既不是UTF-8也不是ASCII的输出(大小中间的不间断空格是0xA0字符)。或者只需删除decode
部分(并使用running=0xA in line
)。
对于我遇到的大多数命令,使用非交互式参数是一个不错的选择。例如,在上述情况下:
conda install package -y
如果你必须要提供提示信息,你可以使用printf hack,例如:
printf 'y\n' | conda install package
这支持多个输入,您可以通过'\n'进行分隔
-y
参数。因此,在(IPython)Jupyter 中使用 conda 安装包的方式是在单元格中键入:!conda -y install package
。 - burkesquires%pip install panda
命令来替代。现在更加简单易用了。然而,OP问题实际上是关于 conda 的 -y
或 --yes
选项,对于这个问题,Matt 的高票答案已经指出可以使用 %conda install
魔术命令。因此,在一个 cell 中这句话是有效的:%conda install scipy -y。 - Wayne!yes | conda install package