Cmd 从Jupyter笔记本运行交互式命令行代码

Cmd 从Jupyter笔记本运行交互式命令行代码,cmd,ipython,jupyter,Cmd,Ipython,Jupyter,ipythonjupyter笔记本中有一个有趣的选项,可以直接从笔记本执行命令行语句。例如: ! mkdir ... ! python file.py !conda install package 此外-此代码可以使用操作系统运行: import os os.system('cmd command') 但是如何运行交互式shell命令呢。例如: ! mkdir ... ! python file.py !conda install package 可能需要将来输入([Y]/N)或文件夹

ipythonjupyter笔记本中有一个有趣的选项,可以直接从笔记本执行命令行语句。例如:

! mkdir ...
! python file.py
!conda install package
此外-此代码可以使用操作系统运行:

import os
os.system('cmd command')
但是如何运行交互式shell命令呢。例如:

! mkdir ...
! python file.py
!conda install package

可能需要将来输入(
[Y]/N
)或文件夹位置,但不接受进一步输入。

我将此作为答案发布。这不是一个好的答案,但我处理这个问题的方法是编写一个bash脚本在后台运行。我已经调查过了它似乎没有太多的文档。我甚至在Jupyter的资料里都找不到。本文:

[关于Jupyter前身和组件IPython的Safari书籍][1]

这表明这只是事情过去的样子,可能永远都是这样。除非你想侵入Jupyter笔记本的魔法命令部分并自己修复

这是说,考虑到一个小的BASH编程(它是简单而有重点的),你可以做你想做的事情,你可以考虑这条路线。尤其是当你需要足够的结果来提高声誉的时候


如果您想根据预期的响应来运行bash脚本,那么这个答案就是您要寻找的:

对于我遇到的大多数命令来说,最好的选择是使用非交互式参数。例如,在上述情况下:

conda install package -y
如果您确实需要提供提示,可以使用printf hack,例如:

printf 'y\n' | conda install package

这支持多个输入,您可以通过“\n”

将它们分开
!命令
语法是
%系统
magic的另一种语法,可以在文档中找到

正如您所猜测的,它正在调用
os.system
,而且只要
os.system
工作,就没有简单的方法可以知道您将运行的进程是否需要用户的输入。因此,当使用笔记本电脑或任何多进程前端时,您无法动态地为正在运行的程序提供输入。(与Python中调用
input
不同,我们可以拦截)

当您明确表示对安装笔记本软件包感兴趣时,我建议您阅读这篇文章,这是关于这个主题的最新讨论的摘要,并解释一下这样做的一些复杂性。当然,您可以使用conda的
——yes
选项,但这并不保证使用conda安装始终有效


还要注意,
!command
是一个IPython功能,而不是Jupyter功能。

假设您询问的是交互性,您可以尝试一些东西

如果您想知道Jupyter如何知道单元格的输出何时结束:显然,它不知道,它只是将捕获的输出转储到最近活动的单元格中:

import threading,time
a=5
threading.Thread(target=lambda:[print(a),time.sleep(20),print(a)]).start()
(故意比好的示例短,因为这只是侧面信息。在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()

即使是
b'ls\nexit\n'
也能工作,这就是为什么
outLoop
如此之长(一个简单的
而(proc.poll()没有)
-
打印(…)
循环会比它抓取所有输出更快完成

然后整个过程可以自动化,如下所示:

while(proc.poll() is None):
    inp=bytearray(input('something: ')+'\n',sys.stdin.encoding)
    if(proc.poll() is None):
        pin.write(inp)
        pin.flush()
这在上运行得很好,但显然我不想尝试在那里安装conda软件包,所以我不知道conda提出问题时会发生什么

幸运的是,输入字段停留在单元格的底部(使用
ls;sleep 10;ls
)进行测试。不幸的是,输入字段需要在末尾添加一个条目才能消失(这已经是“好”的方式,当它是一个简单的
而(…)
-
写入(bytearray(input())
-
刷新()
3-liner,它正在退出,但出现异常


如果有人想在Windows上尝试此功能,它可以与
'cmd'
配合使用,但我建议使用硬编码的
'Windows-1252'
而不是
sys.stdin/out.encoding
:他们说是UTF-8,但一个简单的
dir
命令已经产生了既不是UTF-8也不是ASCII的输出(大小为3位的组之间的不可分割空格为0xA0字符)。或者只需删除
解码部分(并在第行使用
running=0xA

我知道这是一篇旧文章,但我没有看到提到的内容:

!yes | conda install package

这会在回答任何悬而未决的“是/否?”问题时输入“是”。显然,请谨慎使用-只有在您绝对确定“是”时回答正确。

快速提问:你问的是哪一个操作系统?对于这个问题,我认为很重要。显然,如果你想进入Bash shell,你可以进入,但如果你在Windows上,这不会有多大区别。我想这与其中3个操作系统有关,但我对Mac OS系统特别感兴趣。Mac可能有一个Bash shell、 我明天会研究它。从上面的答案来看,它似乎没有那么清楚,但最重要的部分在那里。要在Jupyter笔记本中自动批准conda软件包的安装,您可以使用
-y
参数。因此,在a(IPython)的单元格中使用conda安装软件包的方法Jupyter将键入:<代码>!CODDA -Y安装包。这个问题的答案不完整,但它解决了我的用例,可能大多数其他人都考虑用终端命令或用后背代码来编写FAR命令。如果您解释该命令是什么,谢谢。我更新了我的响应。谢谢您的详细说明。有没有办法让这个机制在Jupyter提供的交互式shell脚本(根据用户提供的选项工作)中工作?