简体   繁体   English

Bash命令不会在Jupyter Notebook中执行

[英]Bash command won't execute in Jupyter Notebook

I am trying to execute a Bash command from inside of a Jupyter Notebook that writes a random number to some files. 我试图从Jupyter笔记本内部执行Bash命令,该笔记本将随机数写入某些文件。 The command I'd like to issue is 我想发出的命令是

echo $(( RANDOM )) &> {output_files[i]}

where output_files is a Python list of output filenames. 其中output_files是输出文件名的Python列表。 I can't figure out how to put the Python variable output_files[i] into a Bash command successfully, so instead I create the entire command as a string and try to execute that through the Notebook: 我无法弄清楚如何将Python变量output_files[i]成功放入Bash命令,因此我将整个命令创建为字符串并尝试通过Notebook执行:

# Create a list of 5 filenames
output_files = [os.path.join(os.getcwd(), 'random-%s.txt' % i) for i in range (5)]

# Write random number to each file
for i in range (5):
    command = "echo $(( RANDOM )) &> " + output_files[i]
    print(command)
    !{command}

When I try this, the files ./random-0.txt etc. are created, but no number is written to them - they are empty. 当我尝试这个时,创建文件./random-0.txt等,但没有写入任何数字 - 它们是空的。 When I run the created commands directly in the terminal, though, it works exactly as expected. 但是,当我直接在终端中运行创建的命令时,它完全按预期工作。 The files are created and contain a single random number each. 创建文件并包含每个随机数。 The print(command) line produces print(command)行产生

echo $(( RANDOM )) &> /filepath/random-0.txt
0
echo $(( RANDOM )) &> /filepath/random-1.txt
echo $(( RANDOM )) &> /filepath/random-2.txt
echo $(( RANDOM )) &> /filepath/random-3.txt
echo $(( RANDOM )) &> /filepath/random-4.txt

Web searches for this problem give hits for several similar questions on Stack Overflow as well as blogs, but the result of all of them is either "Bash commands don't exist on Windows" or "You can use '!' Web搜索此问题会给Stack Overflow和博客上的几个类似问题带来点击,但所有这些问题的结果都是“Windows上不存在Bash命令”或“你可以使用'!' to execute Bash commands in Jupyter Notebooks!" 在Jupyter笔记本中执行Bash命令!“ with no further information about how it works so that I could debug an issue like this. 没有关于它如何工作的进一步信息,以便我可以调试这样的问题。

How do I make this work? 我该如何工作?

Why not do the whole thing in python itself? 为什么不在python本身做整件事? Use the random module the randint() function to generate your numbers. 使用random模块randint()函数生成您的数字。 Define a range of your choice and include it within the (..) 定义您选择的范围并将其包含在(..)

import os
import random
output_files = [os.path.join(os.getcwd(), 'random-%s.txt' % i) for i in range (5)]
for of in output_files:
    with open(of, "w") as text_file:
        text_file.write(str(random.randint(99,1000)))

Hello and welcome to Stack Overflow, 您好,欢迎来到Stack Overflow,

As far as I can tell, your issue does not arise form the bash command execution with ! 据我所知,你的问题不会出现在执行bash命令的情况下! but rather from the fact that you do not "replace" output_files[i] by its actual content. 而是因为你没有“替换” output_files[i]的实际内容。 When you run the loop 当你运行循环

# Write random number to each file
for i in range (5):
    command = "echo $(( RANDOM )) &> {output_files[i]}"

in each iteration, command will be the literal string "echo $(( RANDOM )) &> {output_files[i]}" . 在每次迭代中, command将是文字字符串"echo $(( RANDOM )) &> {output_files[i]}" As you did in your first line, you should use string substitution to replace a placeholder with the content of output_files[i] : 正如您在第一行中所做的那样,您应该使用字符串替换来替换output_files[i]的内容的占位符:

# Write random number to each file
for i in range (5):
    command = ("echo $(( RANDOM )) &> {%s}"%output_files[i])

To debug such an issue, it is usually a good start to inspect the value of the variable in question. 要调试此类问题,通常是检查相关变量值的良好开端。 The easiest way of doing so is by adding print (x) lines where x is the variable whose content you want to inspect. 最简单的方法是添加print (x)行,其中x是要检查其内容的变量。

In reaction to one of the answers here, let me show how to do this with subprocess.check_call() . 在回答这里的一个答案时,让我演示如何使用subprocess.check_call()来做到这一点。

If you want to use a shell redirection in subprocess , you have to have a shell: 如果要在subprocess使用shell重定向,则必须具有shell:

for i in range(5):
    subprocess.check_call('echo "$RANDOM" >random-{}.txt'.format(i), shell=True)

You could superficially try to get rid of the shell=True ... but then echo and $RANDOM are shell features, too. 你可以表面上试图摆脱shell=True ......但是echo$RANDOM也是shell特性。

A pure-Bash solution would be 纯粹的Bash解决方案就是

!for i in {0..4}; do printf "%s\n" "$RANDOM" >random-"$i".txt; done

(As an aside, the numeric context in $((RANDOM)) is not wrong, but entirely superfluous.) $((RANDOM))$((RANDOM))的数字上下文没有错,但完全是多余的。)

You can interpolate a Python expression into the ! 你可以将Python表达式插入到! command line with {...} . 命令行{...} The following also works, for example: 以下也适用,例如:

!{';'.join(['echo $RANDOM >random-{}.txt'.format(i) for i in range(5)])}

In iPython I can produce the results I expect with the construct you tried: 在iPython中,我可以使用您尝试的构造生成我期望的结果:

in [15]: for i in range(2):
    ...:     c='echo $RANDOM >random-{}.txt'.format(i)
    ...:     !{c}
    ...:

in [16]: !tail random-*.txt
==> random-0.txt <==
15637

==> random-1.txt <==
32475

If Jupyter is using the iPython kernel, I'm thinking this ought to work for you, too. 如果Jupyter正在使用iPython内核,我认为这也应该适合你。

Notice also how I used plain old > redirection rather than &> - there really really really is no sane reason to want error messages to be redirected to the files; 还要注意我是如何使用普通旧的>重定向而不是&> - 确实没有理由将错误消息重定向到文件中; and if a file can't be created, you have absolutely no idea what failed or why, or even that it failed. 如果一个文件不能被创建,你完全不知道失败或为什么,甚至可以说 ,它失败了。 (I suspect this is really the reason for your problems, actually. Permission denied? Disk full? We can't know.) (我怀疑这实际上是你问题的原因,实际上。权限被拒绝了?磁盘已满?我们无法知道。)

I would suggest you use Python to perform this simple task, though. 不过,我建议您使用Python来执行这个简单的任务。 Running a subprocess to perform something which is relatively easy in Python itself is inefficient and clumsy as well as somewhat brittle. 运行子进程来执行Python本身相对容易的操作既低效又笨拙,也有些脆弱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM