问题描述
Ipython Jupyter Notebook中有一个有趣的选项,可以直接从笔记本执行命令行语句.例如:
There is an interesting option in Ipython Jupyter Notebook to execute command line statements directly from the notebook. For example:
! mkdir ...
! python file.py
此外-可以使用os
运行此代码:
Moreover - this code can be run using os
:
import os
os.system('cmd command')
但是我如何运行交互式shell命令.例如:
but how do I run interactive shell commands. For example:
!conda install package
可能需要将来输入([Y]/N
)或文件夹位置,但将不接受其他输入.
may require future input ([Y]/N
) or folder location, but won't accept further input.
推荐答案
假设您正在询问交互性,可以尝试一些方法.
Assuming you are asking about interactivity, there is something you can try.
如果您想知道Jupyter如何知道某个单元格的输出何时结束:显然,它不知道,它只是将捕获的输出转储到最近活动的单元格中:
If you ever wondered how Jupyter knows when the output of a cell ends: well, it apparently does not know, it just dumps any captured output into the most recently active cell:
import threading,time
a=5
threading.Thread(target=lambda:[print(a),time.sleep(20),print(a)]).start()
(故意比尼斯短的例子,因为这只是附带信息.在等待20秒的过程中,您有时间激活另一个单元格,也许可以通过发出a=6
来激活)
(deliberately shorter-than-nice example, as this is just side-info. While the 20-second wait is running you have time to activate another cell, perhaps via issuing an a=6
)
这可用于在从主线程控制它的同时将某些控制台代码的输出输出到屏幕上:
This can be used to get the output of some console code to the screen, while controlling it from the main thread:
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()
然后您可以发出命令,例如
Then you can isssue commands, like
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(...)
循环完成的时间比抓取所有输出的时间还早.
Even b'ls\nexit\n'
works, that is why outLoop
is so long (a simple while(proc.poll() is None)
-print(...)
loop would finish sooner than it has grabbed all output.
然后整个过程可以自动化为:
Then the whole thing can be automated as:
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提出问题时会发生什么.
This works well on https://try.jupyter.org/, but obviously I did not want to try installing conda packages there, so I do not know what happens when conda asks a question.
幸运的是输入字段位于单元格的底部(已通过ls;sleep 10;ls
测试).不幸的是,输入字段最后需要一个额外的输入才能消失(这已经是一种不错"的方式,当它是简单的while(...)
-write(bytearray(input()))
-flush()
3-liner时,异常退出.
A lucky thing is that the input field stays at the bottom of the cell (tested with ls;sleep 10;ls
). An unlucky thing is that the input field needs an extra entry at the end to disappear (and that is already the 'nice' way, when it was a simple while(...)
-write(bytearray(input()))
-flush()
3-liner, it was exiting with an exception.
如果有人想在Windows上尝试此操作,它可以与'cmd'
一起使用,但是我建议使用硬编码的'windows-1252'
而不是sys.stdin/out.encoding
:他们说的是UTF-8,但是简单的dir
命令已经产生了输出这既不是UTF-8也不是ASCII(3位数字组之间的大小不可变的空格是0xA0字符).或者只是删除decode
部分(并使用running=0xA in line
)
If someone wants to try this on Windows, it works with 'cmd'
, but I suggest using a hardcoded 'windows-1252'
instead of sys.stdin/out.encoding
: they say UTF-8, but a simple dir
command already produces output which is neither UTF-8 nor ASCII (the non-breakable space between the 3-digit groups in sizes is a 0xA0 character). Or just remove the decode
part (and use running=0xA in line
)
这篇关于从Jupyter Notebook运行交互式命令行代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!