我使用Python和-c来执行一行循环,即:

python -c "for r in range(10): print 'rob'"

这很好。但是,如果我在for循环之前导入一个模块,就会得到一个语法错误:

python -c "import sys; for r in range(10): print 'rob'"

  File "<string>", line 1
    import sys; for r in range(10): print 'rob'
              ^
SyntaxError: invalid syntax

如何解决这个问题?

对我来说,将它作为一行程序很重要,这样我就可以将它包含在Makefile中。


当前回答

当我需要这样做时,我使用:

python -c "$(echo -e "import sys\nsys.stdout.write('Hello, World!\\\n')")"

注意sys.stdout.write语句中的换行符有三个反斜杠。

其他回答

问题并不在于import语句。它是在for循环之前的任何东西。或者更具体地说,出现在内联块之前的任何东西。

例如,这些都是有效的:

python -c "import sys; print 'rob'"
python -c "import sys; sys.stdout.write('rob\n')"

如果import是一个语句是一个问题,这将工作,但它不是:

python -c "__import__('sys'); for r in range(10): print 'rob'"

对于最基本的例子,你可以这样写:

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

然而,lambdas只能执行表达式,而不能执行语句或多条语句,因此您可能仍然无法执行您想要执行的事情。然而,在生成器表达式、列表理解、lambdas、sys.stdout之间。写,“映射”内置,和一些创造性的字符串插值,你可以做一些强大的一行程序。

问题是,您想要走多远,以及在什么情况下编写一个小的.py文件而让makefile执行不是更好?

python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

工作很好。

使用“[]”内联for循环。

我不是一个真正的大python -但我发现这个语法一次,忘记从哪里来的,所以我想我应该记录它:

如果你使用sys.stdout.write而不是print(区别在于,sys.stdout.write接受圆括号内的函数参数-而print不接受),那么对于一行程序,你可以将命令和for的顺序颠倒,删除分号,并将命令括在方括号中,即:

python -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

我不知道这个语法在Python中是如何调用的:)


一行中的方括号是“列表推导式”;在Python 2.7中注意这一点:

STR=abc
echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); print a"

输出:

<generator object <genexpr> at 0xb771461c>

因此,圆括号/圆括号中的命令被视为“生成器对象”;如果我们通过调用next()来“迭代”它,那么括号内的命令将被执行(注意输出中的“abc”):

echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); a.next() ; print a"

输出:

abc
<generator object <genexpr> at 0xb777b734>

如果我们现在使用方括号——注意我们不需要调用next()来执行命令,它会在赋值时立即执行;然而,后来的检查发现a是None:

echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; print a"

输出:

abc
[None]

这并没有留下太多的信息去寻找——对于方括号的情况——但我偶然发现了这一页,我认为它解释了:

Python技巧和技巧-第一版- Python教程| Dream.In.Code:

If you recall, the standard format of a single line generator is a kind of one line 'for' loop inside brackets. This will produce a 'one-shot' iterable object which is an object you can iterate over in only one direction and which you can't re-use once you reach the end. A 'list comprehension' looks almost the same as a regular one-line generator, except that the regular brackets - ( ) - are replaced by square brackets - [ ]. The major advantage of alist comprehension is that produces a 'list', rather than a 'one-shot' iterable object, so that you can go back and forth through it, add elements, sort, etc.

实际上它是一个列表——只是它的第一个元素在执行时变成了none:

echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin].__class__"

输出:

abc
<type 'list'>

echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin][0]"

输出:

abc
None

列表推导式在5中另有说明。数据结构:5.1.4。列表推导式——Python v2.7.4文档“列表推导式提供了一种简洁的创建列表的方法”;据推测,这就是列表的有限“可执行性”在一行程序中发挥作用的地方。

好吧,希望我没有说得太离谱……

这里有一个单行命令行,包含两个非嵌套的for循环;两者都包含在“列表理解”方括号内:

echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; b=[sys.stdout.write(str(x)) for x in range(2)] ; print a ; print b"

输出:

abc
01[None]
[None, None]

注意,第二个“列表”b现在有两个元素,因为它的for循环显式地运行了两次;然而,sys.stdout.write()在这两种情况下的结果(显然)都是None。

这个脚本提供了一个类似perl的命令行接口:

Pyliner -在命令行上运行任意Python代码的脚本(Python recipe)

如果你不想触摸标准输入并模拟你已经传递了"python cmdfile.py",你可以在Bash shell中执行以下操作:

python <(printf "word=raw_input('Enter word: ')\nimport sys\nfor i in range(5):\n    print(word)")

如您所见,它允许您使用标准输入读取输入数据。shell在内部为输入命令内容创建临时文件。