草庐IT

Python timeit命令行错误: "SyntaxError: EOL while scanning string literal"

coder 2024-06-07 原文

我一直在使用 Python timeit模块很长一段时间,但它只是通过交互式 Python session 或 Unix shell。现在,我尝试在 Windows 命令提示符 (cmd.exe) 中测量一些代码片段,但它显示此错误:

C:\Users\Me>python -m timeit '"-".join(map(str, range(100)))'
Traceback (most recent call last):
  File "C:\Python33\lib\runpy.py", line 160, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "C:\Python33\lib\runpy.py", line 73, in _run_code
    exec(code, run_globals)
  File "C:\Python33\lib\timeit.py", line 334, in <module>
    sys.exit(main())
  File "C:\Python33\lib\timeit.py", line 298, in main
    t = Timer(stmt, setup, timer)
  File "C:\Python33\lib\timeit.py", line 131, in __init__
    code = compile(src, dummy_src_name, "exec")
  File "<timeit-src>", line 6
    '-.join(map(str,
                   ^
SyntaxError: EOL while scanning string literal

这相当令人困惑,因为我没有在字符串中插入任何换行符 - 相反,我实际上直接从 timeit 模块文档中粘贴了示例。

在玩这个的时候,我尝试测试没有任何空格的片段,因为错误标记的字符就在它们之前。即使现在没有发生异常,该模块报告的执行时间也与我传递了一个 pass 语句一样,如下所示:

C:\Users\Me>python -m timeit
100000000 loops, best of 3: 0.013 usec per loop

C:\Users\Me>python -m timeit 'map(str,range(100))'
100000000 loops, best of 3: 0.013 usec per loop

C:\Users\Me>python -m timeit 'map(str,range(1000000000000000))'
100000000 loops, best of 3: 0.013 usec per loop

我确信我正确地调用了模块,因为我在 Unix shell 上粘贴了相同的行并且它们按预期工作。

因为我用 Python 2.7 和 3.3 得到了完全相同的结果(另外,该模块是用纯 Python 编写的,并且已经存在很长时间了)我确信这与 Python 无关,但 Windows相反,命令提示符。

那么,为什么会发生这种奇怪的行为,我该如何解决呢?

最佳答案

tl;dr

对传递给 timeit 模块的语句使用双引号。
示例:

C:\Users\Me>python -m timeit "'-'.join(map(str, range(100)))"
10 loops, best of 3: 28.9 usec per loop

详细解释

bashtcsh 等 Unix shell 相比,单引号在 Windows 命令行中的处理方式不同。

这里有一个小的 python 程序来演示这一点:

import sys
print(sys.argv[1:])

运行它(我们称文件为 cmdtest.py),我们观察到以下内容:

C:\Users\Me\Desktop>python cmdtest.py 1 2 3
['1', '2', '3']

C:\Users\Me\Desktop>python cmdtest.py "1 2 3"
['1 2 3']

C:\Users\Me\Desktop>python cmdtest.py '1 2 3'
["'1", '2', "3'"]

因此,单引号按字面意思处理(即不作为特殊字符)。在 SO 中搜索了一下,我找到了 this great description of argument tokenization by cmd :

When invoking a command from a command window, tokenization of the command line arguments is not done by cmd.exe (a.k.a. "the shell"). Most often the tokenization is done by the newly formed processes' C/C++ runtime, but this is not necessarily so -- for example, if the new process was not written in C/C++, or if the new process chooses to ignore argv and process the raw commandline for itself (e.g. with [GetCommandLine()][1]). At the OS level, Windows passes command lines untokenized as a single string to new processes. This is in contrast to most *nix shells, where the shell tokenizes arguments in a consistent, predictable way before passing them to the newly formed process. All this means that you may experience wildly divergent argument tokenization behavior across different programs on Windows, as individual programs often take argument tokenization into their own hands.

If it sounds like anarchy, it kind of is. However, since a large number of Windows programs do utilize the Microsoft C/C++ runtime's argv, it may be generally useful to understand how the MSVCRT tokenizes arguments. Here is an excerpt:

  • Arguments are delimited by white space, which is either a space or a tab.
  • A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. Note that the caret (^) is not recognized as an escape character or delimiter.

错误 #2

考虑到上述情况,让我们首先解释第二个奇怪的行为(充当 pass 语句的行为),因为它更简单一些。由于单引号按字面解释,调用时:

C:\Users\Me>python -m timeit 'map(str,range(100))'

确切的字符串文字 'map(str,range(100))'(包含引号)作为语句传递给时间。
所以,Python 会看到

"'map(str,range(100))'"

代替

'map(str,range(100))'

作为一个字符串,它实际上并没有做任何事情,并且给出了非常接近于 pass 语句的测量值。


错误 #1

现在第一个错误:
正如为 python timeit 所记录的那样模块:

A multi-line statement may be given by specifying each line as a separate statement argument;

所以,调用时:

C:\Users\Me>python -m timeit '"-".join(map(str, range(100)))'

Python 看到 ["'-.join(map(str,", "range(100)))'"] 作为语句传递给 timeit,模块将其解释为多行声明:

'"-".join(map(str,
range(100)))'

它的第一行是一个字符串,它以单引号开头,但从不关闭,因此(最终)解释了奇怪的 EOL 错误。


解决方案

对时间语句使用双引号可以解决问题。

我也尝试过 Windows PowerShell,它比 cmd.exe 更高级,并且表现出与 Unix shell 类似的行为,但并没有完全解决所有问题我测试的语句。
例如,这是可行的(注意语句中的空格):

PS C:\Users\Me> python -m timeit 'map(str, range(100))'
1000000 loops, best of 3: 0.688 usec per loop

虽然最初的例子没有:

PS C:\Users\Me\Desktop> python -m timeit '"-".join(map(str, range(100)))'
option -. not recognized
use -h/--help for command line help

(不过,我还不是很满意。我宁愿做的是让 cmdPowerShell 像 Unix shell 一样工作,这样我就可以简单地粘贴和时间代码片段。如果有人知道一种快速而肮脏的方法来完成此操作(如果可能的话),以完成答案,那就太棒了。)

关于Python timeit命令行错误: "SyntaxError: EOL while scanning string literal",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23987208/

有关Python timeit命令行错误: "SyntaxError: EOL while scanning string literal"的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  5. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  7. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  8. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  9. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  10. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

随机推荐