我正在尝试从Jupyter Notebook内部执行Bash命令,该命令将随机数写入某些文件。我要发出的命令是
echo $(( RANDOM )) &> {output_files[i]}
其中output_files
是输出文件名的Python列表。我不知道如何将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}
当我尝试此操作时,将创建文件./random-0.txt
等,但是没有写入任何数字-它们为空。但是,当我直接在终端中运行创建的命令时,它的工作原理与预期的完全一样。创建文件并每个文件包含一个随机数。 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
对该问题进行网络搜索会给Stack Overflow和博客上的几个类似问题带来成功,但所有结果都是“ Windows上不存在Bash命令”或“您可以使用'!”。在Jupyter Notebook中执行Bash命令!”没有关于它如何工作的更多信息,以便我可以调试这样的问题。
我如何进行这项工作?
答案 0 :(得分:3)
为什么python
本身没有全部内容?使用random
函数的randint()
模块来生成您的号码。定义您选择的范围,并将其包括在(..)
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)))
答案 1 :(得分:2)
您好,欢迎来到Stack Overflow,
据我所知,您的问题不是由用!
执行bash命令引起的,而是因为您没有用其实际内容“替换” output_files[i]
。
当您运行循环
# Write random number to each file
for i in range (5):
command = "echo $(( RANDOM )) &> {output_files[i]}"
在每次迭代中,command
将是文字字符串"echo $(( RANDOM )) &> {output_files[i]}"
。就像您在第一行中所做的那样,应该使用字符串替换将占位符替换为output_files[i]
的内容:
# Write random number to each file
for i in range (5):
command = ("echo $(( RANDOM )) &> {%s}"%output_files[i])
要调试此类问题,通常是检查相关变量的值的好开始。最简单的方法是添加print (x)
行,其中x
是要检查其内容的变量。
答案 2 :(得分:2)
针对这里的答案之一,让我展示如何使用subprocess.check_call()
来做到这一点。
如果要在subprocess
中使用shell重定向,则必须具有shell:
for i in range(5):
subprocess.check_call('echo "$RANDOM" >random-{}.txt'.format(i), shell=True)
您可以从表面上尝试摆脱shell=True
...,但是echo
和$RANDOM
也是Shell的功能。
一个纯Bash解决方案就是
!for i in {0..4}; do printf "%s\n" "$RANDOM" >random-"$i".txt; done
(顺便说一句,$((RANDOM))
中的数字上下文没有错,但完全是多余的。)
您可以使用!
将Python表达式插入{...}
命令行中。例如,以下内容也适用:
!{';'.join(['echo $RANDOM >random-{}.txt'.format(i) for i in range(5)])}
在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
如果Jupyter使用的是iPython内核,我想这也应该对您有用。
还请注意我是如何使用普通的旧>
重定向而不是&>
的-真的 really really 并没有理智的理由想要错误消息重定向到文件;如果无法创建文件,则您完全不知道什么失败或为什么失败,甚至那失败。 (实际上,我怀疑这确实是您遇到问题的原因。权限被拒绝?磁盘已满?我们不知道。)
不过,我建议您使用Python执行此简单任务。运行子进程来执行某些在Python本身中相对容易实现的操作,效率低下,笨拙且有些脆弱。