分类目录归档:知识问答

如何终止以shell = True启动的python子进程

问题:如何终止以shell = True启动的python子进程

我正在使用以下命令启动子流程:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

但是,当我尝试杀死使用:

p.terminate()

要么

p.kill()

该命令一直在后台运行,所以我想知道如何才能真正终止该过程。

请注意,当我使用以下命令运行命令时:

p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)

发出时,它确实成功终止p.terminate()

I’m launching a subprocess with the following command:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

However, when I try to kill using:

p.terminate()

or

p.kill()

The command keeps running in the background, so I was wondering how can I actually terminate the process.

Note that when I run the command with:

p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)

It does terminate successfully when issuing the p.terminate().


回答 0

使用进程组,以便能够向中的所有进程发送信号。为此,您应该将会话ID附加到生成的子进程的父进程中,在您的情况下,这是一个外壳程序。这将使其成为流程的小组负责人。因此,现在,当信号发送到流程组负责人时,它便被传输到该组的所有子流程。

这是代码:

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups

Use a process group so as to enable sending a signal to all the process in the groups. For that, you should attach a session id to the parent process of the spawned/child processes, which is a shell in your case. This will make it the group leader of the processes. So now, when a signal is sent to the process group leader, it’s transmitted to all of the child processes of this group.

Here’s the code:

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups

回答 1

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()

p.kill()最终终止了shell进程,cmd并且仍在运行。

我通过以下方法找到了一个方便的解决方法:

p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)

这将导致cmd继承shell进程,而不是让shell启动不会被杀死的子进程。 p.pid然后将是您的cmd进程的ID。

p.kill() 应该管用。

我不知道这会对您的管道产生什么影响。

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()

p.kill() ends up killing the shell process and cmd is still running.

I found a convenient fix this by:

p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)

This will cause cmd to inherit the shell process, instead of having the shell launch a child process, which does not get killed. p.pid will be the id of your cmd process then.

p.kill() should work.

I don’t know what effect this will have on your pipe though.


回答 2

如果可以使用psutil,则可以完美地工作:

import subprocess

import psutil


def kill(proc_pid):
    process = psutil.Process(proc_pid)
    for proc in process.children(recursive=True):
        proc.kill()
    process.kill()


proc = subprocess.Popen(["infinite_app", "param"], shell=True)
try:
    proc.wait(timeout=3)
except subprocess.TimeoutExpired:
    kill(proc.pid)

If you can use psutil, then this works perfectly:

import subprocess

import psutil


def kill(proc_pid):
    process = psutil.Process(proc_pid)
    for proc in process.children(recursive=True):
        proc.kill()
    process.kill()


proc = subprocess.Popen(["infinite_app", "param"], shell=True)
try:
    proc.wait(timeout=3)
except subprocess.TimeoutExpired:
    kill(proc.pid)

回答 3

我可以用

from subprocess import Popen

process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))

它杀死了cmd.exe我给命令的程序。

(在Windows上)

I could do it using

from subprocess import Popen

process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))

it killed the cmd.exe and the program that i gave the command for.

(On Windows)


回答 4

shell=Trueshell是子进程时,命令就是它的子进程。因此,任何SIGTERMSIGKILL将杀死外壳程序但不会杀死它的子进程的过程,我不记得有什么好方法。我能想到的最好方法是使用shell=False,否则当您杀死父shell进程时,它将留下一个已失效的shell进程。

When shell=True the shell is the child process, and the commands are its children. So any SIGTERM or SIGKILL will kill the shell but not its child processes, and I don’t remember a good way to do it. The best way I can think of is to use shell=False, otherwise when you kill the parent shell process, it will leave a defunct shell process.


回答 5

这些答案均不适合我,因此我留下了有效的代码。就我而言,即使在终止进程.kill()并获得.poll()返回代码后,进程也没有终止。

按照subprocess.Popen 文档

“ …为了正确清理行为良好的应用程序,应终止子进程并完成通信…”

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

就我而言,我proc.communicate()在打电话后就错过了proc.kill()。这将清理进程stdin,stdout …,并终止进程。

None of this answers worked for me so Im leaving the code that did work. In my case even after killing the process with .kill() and getting a .poll() return code the process didn’t terminate.

Following the subprocess.Popen documentation:

“…in order to cleanup properly a well-behaved application should kill the child process and finish communication…”

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

In my case I was missing the proc.communicate() after calling proc.kill(). This cleans the process stdin, stdout … and does terminate the process.


回答 6

正如Sai所说,shell是孩子,因此信号被它拦截了-我发现的最佳方法是使用shell = False并使用shlex拆分命令行:

if isinstance(command, unicode):
    cmd = command.encode('utf8')
args = shlex.split(cmd)

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

然后p.kill()和p.terminate()应该可以按照您的期望工作。

As Sai said, the shell is the child, so signals are intercepted by it — best way I’ve found is to use shell=False and use shlex to split the command line:

if isinstance(command, unicode):
    cmd = command.encode('utf8')
args = shlex.split(cmd)

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Then p.kill() and p.terminate() should work how you expect.


回答 7

我觉得我们可以使用:

import os
import signal
import subprocess
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

os.killpg(os.getpgid(pro.pid), signal.SIGINT)

这不会杀死您的所有任务,但会杀死p.pid进程

what i feel like we could use:

import os
import signal
import subprocess
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

os.killpg(os.getpgid(pro.pid), signal.SIGINT)

this will not kill all your task but the process with the p.pid


回答 8

我知道这是一个古老的问题,但这可能会对寻求其他方法的人有所帮助。这就是我在Windows上用来杀死已调用进程的方法。

si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
subprocess.call(["taskkill", "/IM", "robocopy.exe", "/T", "/F"], startupinfo=si)

/ IM是图像名称,如果需要,您也可以执行/ PID。/ T杀死进程以及子进程。/ F强制终止它。如我所设置的,si是如何执行此操作而不显示CMD窗口。此代码在python 3中使用。

I know this is an old question but this may help someone looking for a different method. This is what I use on windows to kill processes that I’ve called.

si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
subprocess.call(["taskkill", "/IM", "robocopy.exe", "/T", "/F"], startupinfo=si)

/IM is the image name, you can also do /PID if you want. /T kills the process as well as the child processes. /F force terminates it. si, as I have it set, is how you do this without showing a CMD window. This code is used in python 3.


回答 9

将信号发送到组中的所有进程

    self.proc = Popen(commands, 
            stdout=PIPE, 
            stderr=STDOUT, 
            universal_newlines=True, 
            preexec_fn=os.setsid)

    os.killpg(os.getpgid(self.proc.pid), signal.SIGHUP)
    os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)

Send the signal to all the processes in group

    self.proc = Popen(commands, 
            stdout=PIPE, 
            stderr=STDOUT, 
            universal_newlines=True, 
            preexec_fn=os.setsid)

    os.killpg(os.getpgid(self.proc.pid), signal.SIGHUP)
    os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)

回答 10

我在这里没有看到此内容,因此我将其放在此处,以防有人需要。如果您要做的只是确保子流程成功终止,则可以将其放在上下文管理器中。例如,我希望我的标准打印机打印出图像,并使用上下文管理器确保子进程终止。

import subprocess

with open(filename,'rb') as f:
    img=f.read()
with subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE) as lpr:
    lpr.stdin.write(img)
print('Printed image...')

我相信这种方法也是跨平台的。

I have not seen this mentioned here, so I am putting it out there in case someone needs it. If all you want to do is to make sure that your subprocess terminates successfully, you could put it in a context manager. For example, I wanted my standard printer to print an out image and using the context manager ensured that the subprocess terminated.

import subprocess

with open(filename,'rb') as f:
    img=f.read()
with subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE) as lpr:
    lpr.stdin.write(img)
print('Printed image...')

I believe this method is also cross-platform.


从另一个脚本调用一个脚本的最佳方法是什么?

问题:从另一个脚本调用一个脚本的最佳方法是什么?

我有一个名为test1.py的脚本,该脚本不在模块中。它只包含应在脚本本身运行时执行的代码。没有函数,类,方法等。我有另一个作为服务运行的脚本。我想从作为服务运行的脚本中调用test1.py。

例如:

文件test1.py

print "I am a test"
print "see! I do nothing productive."

文件service.py

# Lots of stuff here
test1.py # do whatever is in test1.py

我知道一种方法是打开文件,读取内容并进行基本评估。我假设有一种更好的方法。或者至少我希望如此。

I have a script named test1.py which is not in a module. It just has code that should execute when the script itself is run. There are no functions, classes, methods, etc. I have another script which runs as a service. I want to call test1.py from the script running as a service.

For example:

File test1.py

print "I am a test"
print "see! I do nothing productive."

File service.py

# Lots of stuff here
test1.py # do whatever is in test1.py

I’m aware of one method which is opening the file, reading the contents, and basically eval’ing it. I’m assuming there’s a better way of doing this. Or at least I hope so.


回答 0

这样做的通常方法如下。

test1.py

def some_func():
    print 'in test 1, unproductive'

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()

service.py

import test1

def service_func():
    print 'service func'

if __name__ == '__main__':
    # service.py executed as script
    # do something
    service_func()
    test1.some_func()

The usual way to do this is something like the following.

test1.py

def some_func():
    print 'in test 1, unproductive'

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()

service.py

import test1

def service_func():
    print 'service func'

if __name__ == '__main__':
    # service.py executed as script
    # do something
    service_func()
    test1.some_func()

回答 1

这可能在Python 2中使用

execfile("test2.py")

如果对您而言很重要,请参阅有关命名空间处理的文档

在Python 3中,可以使用(感谢@fantastory)

exec(open("test2.py").read())

但是,您应该考虑使用其他方法。您的想法(据我所见)看起来不太干净。

This is possible in Python 2 using

execfile("test2.py")

See the documentation for the handling of namespaces, if important in your case.

In Python 3, this is possible using (thanks to @fantastory)

exec(open("test2.py").read())

However, you should consider using a different approach; your idea (from what I can see) doesn’t look very clean.


回答 2

另一种方式:

文件test1.py:

print "test1.py"

文件service.py:

import subprocess

subprocess.call("test1.py", shell=True)

该方法的优点是您不必编辑现有的Python脚本即可将其所有代码放入子例程中。

文档:Python 2Python 3

Another way:

File test1.py:

print "test1.py"

File service.py:

import subprocess

subprocess.call("test1.py", shell=True)

The advantage to this method is that you don’t have to edit an existing Python script to put all its code into a subroutine.

Documentation: Python 2, Python 3


回答 3

如果您希望test1.py保持可执行性,并且具有与在service.py内部调用时相同的功能,请执行以下操作:

test1.py

def main():
    print "I am a test"
    print "see! I do nothing productive."

if __name__ == "__main__":
    main()

service.py

import test1
# lots of stuff here
test1.main() # do whatever is in test1.py

If you want test1.py to remain executable with the same functionality as when it’s called inside service.py, then do something like:

test1.py

def main():
    print "I am a test"
    print "see! I do nothing productive."

if __name__ == "__main__":
    main()

service.py

import test1
# lots of stuff here
test1.main() # do whatever is in test1.py

回答 4

import os

os.system("python myOtherScript.py arg1 arg2 arg3")  

使用os,您可以直接拨打终端电话。如果您想更具体一些,可以将输入字符串与局部变量连接在一起,即。

command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)
import os

os.system("python myOtherScript.py arg1 arg2 arg3")  

Using os you can make calls directly to your terminal. If you want to be even more specific you can concatenate your input string with local variables, ie.

command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)

回答 5

您不应该这样做。相反,请执行以下操作:

test1.py:

 def print_test():
      print "I am a test"
      print "see! I do nothing productive."

service.py

#near the top
from test1 import print_test
#lots of stuff here
print_test()

You should not be doing this. Instead, do:

test1.py:

 def print_test():
      print "I am a test"
      print "see! I do nothing productive."

service.py

#near the top
from test1 import print_test
#lots of stuff here
print_test()

回答 6

使用import test1的第一个用途-它会执行脚本。对于以后的调用,请将脚本视为导入的模块,然后调用该reload(test1)方法。

reload(module)被执行:

  • 重新编译Python模块的代码并重新执行模块级代码,从而定义了一组新对象,这些对象绑定到模块字典中的名称。扩展模块的init函数未调用

一个简单的检查sys.modules可用于调用适当的操作。要始终将脚本名称引用为字符串('test1'),请使用内置的import()’

import sys
if sys.modules.has_key['test1']:
    reload(sys.modules['test1'])
else:
    __import__('test1')

Use import test1 for the 1st use – it will execute the script. For later invocations, treat the script as an imported module, and call the reload(test1) method.

When reload(module) is executed:

  • Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called

A simple check of sys.modules can be used to invoke the appropriate action. To keep referring to the script name as a string ('test1'), use the import()’ builtin.

import sys
if sys.modules.has_key['test1']:
    reload(sys.modules['test1'])
else:
    __import__('test1')

回答 7

我更喜欢runpy

#!/usr/bin/env python
# coding: utf-8

import runpy

runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')

I prefer runpy:

#!/usr/bin/env python
# coding: utf-8

import runpy

runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')


回答 8

为什么不仅仅导入test1?每个python脚本都是一个模块。更好的方法是在test1.py中具有main / run等功能,导入test1并运行test1.main()。或者,您可以将test1.py作为子进程执行。

Why not just import test1? Every python script is a module. A better way would be to have a function e.g. main/run in test1.py, import test1 and run test1.main(). Or you can execute test1.py as a subprocess.


回答 9

如前所述,这runpy是从当前脚本运行其他脚本或模块的一种好方法。

顺便说一句,跟踪器或调试器执行此操作非常普遍,在这种情况下,直接导入文件或在子进程中运行文件之类的方法通常不起作用。

还需要注意使用它exec来运行代码。您必须提供适当的信息run_globals以避免导入错误或其他问题。runpy._run_code有关详情,请参阅。

As it’s already mentioned, runpy is a nice way to run other scripts or modules from current script.

By the way, it’s quite common for a tracer or debugger to do this, and under such circumstances methods like importing the file directly or running the file in a subprocess usually do not work.

It also needs attention to use exec to run the code. You have to provide proper run_globals to avoid import error or some other issues. Refer to runpy._run_code for details.


回答 10

这是一个带subprocess库的示例:

import subprocess

python_version = '3'
path_to_run = './'
py_name = '__main__.py'

# args = [f"python{python_version}", f"{path_to_run}{py_name}"]  # Avaible in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]

res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

This is an example with subprocess library:

import subprocess

python_version = '3'
path_to_run = './'
py_name = '__main__.py'

# args = [f"python{python_version}", f"{path_to_run}{py_name}"]  # Avaible in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]

res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

回答 11

这个过程有些不合常规,但可以在所有python版本中使用,

假设您要在“ if”条件下执行名为“ recommend.py”的脚本,然后使用,

if condition:
       import recommend

技术不同,但是有效!

This process is somewhat un-orthodox, but would work across all python versions,

Suppose you want to execute a script named ‘recommend.py’ inside an ‘if’ condition, then use,

if condition:
       import recommend

The technique is different, but works!


如何将本地时间字符串转换为UTC?

问题:如何将本地时间字符串转换为UTC?

如何将本地时间的datetime 字符串转换为UTC时间字符串

我确定我之前已经做过,但是找不到它,因此SO希望将来可以帮助我(和其他人)做到这一点。

说明:例如,如果我2008-09-17 14:02:00在当地的时区(+10)中,我想生成一个具有相等UTC时间的字符串:2008-09-17 04:02:00

另外,从http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/,请注意,一般来说这是不可能的,因为DST和其他问题没有从本地时间到本地的唯一转换。 UTC时间。

How do I convert a datetime string in local time to a string in UTC time?

I’m sure I’ve done this before, but can’t find it and SO will hopefully help me (and others) do that in future.

Clarification: For example, if I have 2008-09-17 14:02:00 in my local timezone (+10), I’d like to generate a string with the equivalent UTC time: 2008-09-17 04:02:00.

Also, from http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/, note that in general this isn’t possible as with DST and other issues there is no unique conversion from local time to UTC time.


回答 0

首先,将字符串解析为一个简单的datetime对象。这是的实例,datetime.datetime没有附加的时区信息。请参阅文档以datetime.strptime获取有关解析日期字符串的信息。

使用pytz包含时区+ UTC完整列表的模块。弄清楚本地时区是什么,从中构造一个时区对象,然后将其操纵并附加到原始日期时间。

最后,使用datetime.astimezone()方法将日期时间转换为UTC。

使用本地时区“ America / Los_Angeles”的字符串“ 2001-2-3 10:11:12”的源代码:

import pytz, datetime
local = pytz.timezone ("America/Los_Angeles")
naive = datetime.datetime.strptime ("2001-2-3 10:11:12", "%Y-%m-%d %H:%M:%S")
local_dt = local.localize(naive, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)

从那里,您可以strftime()根据需要使用该方法格式化UTC日期时间:

utc_dt.strftime ("%Y-%m-%d %H:%M:%S")

First, parse the string into a naive datetime object. This is an instance of datetime.datetime with no attached timezone information. See documentation for datetime.strptime for information on parsing the date string.

Use the pytz module, which comes with a full list of time zones + UTC. Figure out what the local timezone is, construct a timezone object from it, and manipulate and attach it to the naive datetime.

Finally, use datetime.astimezone() method to convert the datetime to UTC.

Source code, using local timezone “America/Los_Angeles”, for the string “2001-2-3 10:11:12”:

import pytz, datetime
local = pytz.timezone ("America/Los_Angeles")
naive = datetime.datetime.strptime ("2001-2-3 10:11:12", "%Y-%m-%d %H:%M:%S")
local_dt = local.localize(naive, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)

From there, you can use the strftime() method to format the UTC datetime as needed:

utc_dt.strftime ("%Y-%m-%d %H:%M:%S")

回答 1

datetime模块的utcnow()函数可用于获取当前UTC时间。

>>> import datetime
>>> utc_datetime = datetime.datetime.utcnow()
>>> utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2010-02-01 06:59:19'

正如汤姆在上面提到的链接:http : //lucumr.pocoo.org/2011/7/15/eppur-si-muove/ 所说:

UTC是没有夏令时的时区,并且仍然是过去没有配置更改的时区。

始终在UTC中测量和存储时间

如果您需要记录时间,将其分开存储。 不要存储本地时间+时区信息!

注意 -如果您的任何数据位于使用DST的区域中,请使用pytz并查看John Millikin的答案。

如果您想从给定的字符串中获取UTC时间,并且很幸运地处于世界上不使用DST的区域中,或者您的数据仅与UTC偏移而未应用DST:

->使用本地时间作为偏移值的基础:

>>> # Obtain the UTC Offset for the current system:
>>> UTC_OFFSET_TIMEDELTA = datetime.datetime.utcnow() - datetime.datetime.now()
>>> local_datetime = datetime.datetime.strptime("2008-09-17 14:04:00", "%Y-%m-%d %H:%M:%S")
>>> result_utc_datetime = local_datetime + UTC_OFFSET_TIMEDELTA
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

->或者,使用已知的偏移量,使用datetime.timedelta():

>>> UTC_OFFSET = 10
>>> result_utc_datetime = local_datetime - datetime.timedelta(hours=UTC_OFFSET)
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

更新:

由于python 3.2 datetime.timezone可用。您可以使用以下命令生成时区感知日期时间对象:

import datetime

timezone_aware_dt = datetime.datetime.now(datetime.timezone.utc)

如果您准备进行时区转换,请阅读以下内容:

https://medium.com/@eleroy/10-things-you-need-to-know-about-date-and-time-in-python-with-datetime-pytz-dateutil-timedelta-309bfbafb3f7

NOTE — As of 2020 you should not be using .utcnow() or .utcfromtimestamp(xxx). As you’ve presumably moved on to python3,you should be using timezone aware datetime objects.

>>> from datetime import timezone
>>> dt_now = datetime.now(tz=timezone.utc)
>>> dt_ts = datetime.fromtimestamp(1571595618.0, tz=timezone.utc)

for details see: see: https://blog.ganssle.io/articles/2019/11/utcnow.html

original answer (from 2010):

The datetime module’s utcnow() function can be used to obtain the current UTC time.

>>> import datetime
>>> utc_datetime = datetime.datetime.utcnow()
>>> utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2010-02-01 06:59:19'

As the link mentioned above by Tom: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ says:

UTC is a timezone without daylight saving time and still a timezone without configuration changes in the past.

Always measure and store time in UTC.

If you need to record where the time was taken, store that separately. Do not store the local time + timezone information!

NOTE – If any of your data is in a region that uses DST, use pytz and take a look at John Millikin’s answer.

If you want to obtain the UTC time from a given string and your lucky enough to be in a region in the world that either doesn’t use DST, or you have data that is only offset from UTC without DST applied:

–> using local time as the basis for the offset value:

>>> # Obtain the UTC Offset for the current system:
>>> UTC_OFFSET_TIMEDELTA = datetime.datetime.utcnow() - datetime.datetime.now()
>>> local_datetime = datetime.datetime.strptime("2008-09-17 14:04:00", "%Y-%m-%d %H:%M:%S")
>>> result_utc_datetime = local_datetime + UTC_OFFSET_TIMEDELTA
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

–> Or, from a known offset, using datetime.timedelta():

>>> UTC_OFFSET = 10
>>> result_utc_datetime = local_datetime - datetime.timedelta(hours=UTC_OFFSET)
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

UPDATE:

Since python 3.2 datetime.timezone is available. You can generate a timezone aware datetime object with the command below:

import datetime

timezone_aware_dt = datetime.datetime.now(datetime.timezone.utc)

If your ready to take on timezone conversions go read this:

https://medium.com/@eleroy/10-things-you-need-to-know-about-date-and-time-in-python-with-datetime-pytz-dateutil-timedelta-309bfbafb3f7


回答 2

感谢@rofly,从字符串到字符串的完整转换如下:

time.strftime("%Y-%m-%d %H:%M:%S", 
              time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00", 
                                                    "%Y-%m-%d %H:%M:%S"))))

我对time/ calendar函数的总结:

time.strptime
字符串->元组(未应用时区,因此匹配字符串)

time.mktime
当地时间元组->自纪元以来的秒数(始终为当地时间)

time.gmtime
自纪元以来的秒数-> UTC中的元组

calendar.timegm
以UTC表示的元组->自历元以来的秒数

time.localtime
自纪元以来的秒数->当地时区中的元组

Thanks @rofly, the full conversion from string to string is as follows:

time.strftime("%Y-%m-%d %H:%M:%S", 
              time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00", 
                                                    "%Y-%m-%d %H:%M:%S"))))

My summary of the time/calendar functions:

time.strptime
string –> tuple (no timezone applied, so matches string)

time.mktime
local time tuple –> seconds since epoch (always local time)

time.gmtime
seconds since epoch –> tuple in UTC

and

calendar.timegm
tuple in UTC –> seconds since epoch

time.localtime
seconds since epoch –> tuple in local timezone


回答 3

这是常见的Python时间转换的摘要。

某些方法会损失几分之一秒,并用(s)标记。ts = (d - epoch) / unit可以使用诸如的显式公式代替(感谢jfs)。

  • struct_time(UTC)→POSIX (s)
    calendar.timegm(struct_time)
  • 原始日期时间(本地)→POSIX (秒):(
    calendar.timegm(stz.localize(dt, is_dst=None).utctimetuple())
    DST转换期间的异常,请参阅jfs的注释)
  • 原始日期时间(UTC)→POSIX (s)
    calendar.timegm(dt.utctimetuple())
  • 知道日期时间→POSIX (S)
    calendar.timegm(dt.utctimetuple())
  • POSIX→struct_time(UTC,s):(
    time.gmtime(t)
    请参阅jfs的评论)
  • 原始日期时间(本地)→struct_time(UTC,s):(
    stz.localize(dt, is_dst=None).utctimetuple()
    DST转换期间的异常,请参阅jfs的注释)
  • 原始日期时间(UTC)→struct_time(UTC,s):
    dt.utctimetuple()
  • 知道日期时间→struct_time(UTC,s):
    dt.utctimetuple()
  • POSIX→原始日期时间(本地):(
    datetime.fromtimestamp(t, None)
    在某些情况下可能会失败,请参见下面来自jfs的评论)
  • struct_time(UTC)→原始日期时间(本地,s):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
    不能表示leap秒,请参见jfs的注释)
  • 原始日期时间(UTC)→原始日期时间(本地):
    dt.replace(tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
  • 知道日期时间→天真日期时间(本地):
    dt.astimezone(tz).replace(tzinfo=None)
  • POSIX→原始日期时间(UTC):
    datetime.utcfromtimestamp(t)
  • struct_time(UTC)→原始日期时间(UTC,s):(
    datetime.datetime(*struct_time[:6])
    不能表示leap秒,请参阅jfs的注释)
  • 原始日期时间(本地)→原始日期时间(UTC):
    stz.localize(dt, is_dst=None).astimezone(UTC).replace(tzinfo=None)
    DST转换期间的异常,请参阅jfs的注释)
  • 知道日期时间→原始日期时间(UTC):
    dt.astimezone(UTC).replace(tzinfo=None)
  • POSIX→知道日期时间:
    datetime.fromtimestamp(t, tz)
    对于非pytz时区可能会失败)
  • struct_time(UTC)→感知日期时间(S)
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz)
    不能表示leap秒,请参阅jfs的注释)
  • 原始日期时间(本地)→感知日期时间:
    stz.localize(dt, is_dst=None)
    (DST转换期间的异常,请参阅jfs的注释)
  • 原始日期时间(UTC)→知道日期时间:
    dt.replace(tzinfo=UTC)

资料来源:taaviburns.ca

Here’s a summary of common Python time conversions.

Some methods drop fractions of seconds, and are marked with (s). An explicit formula such as ts = (d - epoch) / unit can be used instead (thanks jfs).

  • struct_time (UTC) → POSIX (s):
    calendar.timegm(struct_time)
  • Naïve datetime (local) → POSIX (s):
    calendar.timegm(stz.localize(dt, is_dst=None).utctimetuple())
    (exception during DST transitions, see comment from jfs)
  • Naïve datetime (UTC) → POSIX (s):
    calendar.timegm(dt.utctimetuple())
  • Aware datetime → POSIX (s):
    calendar.timegm(dt.utctimetuple())
  • POSIX → struct_time (UTC, s):
    time.gmtime(t)
    (see comment from jfs)
  • Naïve datetime (local) → struct_time (UTC, s):
    stz.localize(dt, is_dst=None).utctimetuple()
    (exception during DST transitions, see comment from jfs)
  • Naïve datetime (UTC) → struct_time (UTC, s):
    dt.utctimetuple()
  • Aware datetime → struct_time (UTC, s):
    dt.utctimetuple()
  • POSIX → Naïve datetime (local):
    datetime.fromtimestamp(t, None)
    (may fail in certain conditions, see comment from jfs below)
  • struct_time (UTC) → Naïve datetime (local, s):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
    (can’t represent leap seconds, see comment from jfs)
  • Naïve datetime (UTC) → Naïve datetime (local):
    dt.replace(tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
  • Aware datetime → Naïve datetime (local):
    dt.astimezone(tz).replace(tzinfo=None)
  • POSIX → Naïve datetime (UTC):
    datetime.utcfromtimestamp(t)
  • struct_time (UTC) → Naïve datetime (UTC, s):
    datetime.datetime(*struct_time[:6])
    (can’t represent leap seconds, see comment from jfs)
  • Naïve datetime (local) → Naïve datetime (UTC):
    stz.localize(dt, is_dst=None).astimezone(UTC).replace(tzinfo=None)
    (exception during DST transitions, see comment from jfs)
  • Aware datetime → Naïve datetime (UTC):
    dt.astimezone(UTC).replace(tzinfo=None)
  • POSIX → Aware datetime:
    datetime.fromtimestamp(t, tz)
    (may fail for non-pytz timezones)
  • struct_time (UTC) → Aware datetime (s):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz)
    (can’t represent leap seconds, see comment from jfs)
  • Naïve datetime (local) → Aware datetime:
    stz.localize(dt, is_dst=None)
    (exception during DST transitions, see comment from jfs)
  • Naïve datetime (UTC) → Aware datetime:
    dt.replace(tzinfo=UTC)

Source: taaviburns.ca


回答 4

def local_to_utc(t):
    secs = time.mktime(t)
    return time.gmtime(secs)

def utc_to_local(t):
    secs = calendar.timegm(t)
    return time.localtime(secs)

资料来源:http : //feihonghsu.blogspot.com/2008/02/converting-from-local-time-to-utc.html

bd808的用法示例:如果您的源是datetime.datetimeobject t,则调用为:

local_to_utc(t.timetuple())
def local_to_utc(t):
    secs = time.mktime(t)
    return time.gmtime(secs)

def utc_to_local(t):
    secs = calendar.timegm(t)
    return time.localtime(secs)

Source: http://feihonghsu.blogspot.com/2008/02/converting-from-local-time-to-utc.html

Example usage from bd808: If your source is a datetime.datetime object t, call as:

local_to_utc(t.timetuple())

回答 5

我对dateutil感到好运(广泛建议在SO上解决其他相关问题):

from datetime import *
from dateutil import *
from dateutil.tz import *

# METHOD 1: Hardcode zones:
utc_zone = tz.gettz('UTC')
local_zone = tz.gettz('America/Chicago')
# METHOD 2: Auto-detect zones:
utc_zone = tz.tzutc()
local_zone = tz.tzlocal()

# Convert time string to datetime
local_time = datetime.strptime("2008-09-17 14:02:00", '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in local time zone since 
# datetime objects are 'naive' by default
local_time = local_time.replace(tzinfo=local_zone)
# Convert time to UTC
utc_time = local_time.astimezone(utc_zone)
# Generate UTC time string
utc_string = utc_time.strftime('%Y-%m-%d %H:%M:%S')

(代码从此答案派生而来,将UTC datetime字符串转换为本地datetime

I’m having good luck with dateutil (which is widely recommended on SO for other related questions):

from datetime import *
from dateutil import *
from dateutil.tz import *

# METHOD 1: Hardcode zones:
utc_zone = tz.gettz('UTC')
local_zone = tz.gettz('America/Chicago')
# METHOD 2: Auto-detect zones:
utc_zone = tz.tzutc()
local_zone = tz.tzlocal()

# Convert time string to datetime
local_time = datetime.strptime("2008-09-17 14:02:00", '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in local time zone since 
# datetime objects are 'naive' by default
local_time = local_time.replace(tzinfo=local_zone)
# Convert time to UTC
utc_time = local_time.astimezone(utc_zone)
# Generate UTC time string
utc_string = utc_time.strftime('%Y-%m-%d %H:%M:%S')

(Code was derived from this answer to Convert UTC datetime string to local datetime)


回答 6

pytz的另一个示例,但包含localize(),这节省了我的时间。

import pytz, datetime
utc = pytz.utc
fmt = '%Y-%m-%d %H:%M:%S'
amsterdam = pytz.timezone('Europe/Amsterdam')

dt = datetime.datetime.strptime("2012-04-06 10:00:00", fmt)
am_dt = amsterdam.localize(dt)
print am_dt.astimezone(utc).strftime(fmt)
'2012-04-06 08:00:00'

One more example with pytz, but includes localize(), which saved my day.

import pytz, datetime
utc = pytz.utc
fmt = '%Y-%m-%d %H:%M:%S'
amsterdam = pytz.timezone('Europe/Amsterdam')

dt = datetime.datetime.strptime("2012-04-06 10:00:00", fmt)
am_dt = amsterdam.localize(dt)
print am_dt.astimezone(utc).strftime(fmt)
'2012-04-06 08:00:00'

回答 7

我在python-dateutil上获得了最大的成功:

from dateutil import tz

def datetime_to_utc(date):
    """Returns date in UTC w/o tzinfo"""
    return date.astimezone(tz.gettz('UTC')).replace(tzinfo=None) if date.tzinfo else date

I’ve had the most success with python-dateutil:

from dateutil import tz

def datetime_to_utc(date):
    """Returns date in UTC w/o tzinfo"""
    return date.astimezone(tz.gettz('UTC')).replace(tzinfo=None) if date.tzinfo else date

回答 8

import time

import datetime

def Local2UTC(LocalTime):

    EpochSecond = time.mktime(LocalTime.timetuple())
    utcTime = datetime.datetime.utcfromtimestamp(EpochSecond)

    return utcTime

>>> LocalTime = datetime.datetime.now()

>>> UTCTime = Local2UTC(LocalTime)

>>> LocalTime.ctime()

'Thu Feb  3 22:33:46 2011'

>>> UTCTime.ctime()

'Fri Feb  4 05:33:46 2011'
import time

import datetime

def Local2UTC(LocalTime):

    EpochSecond = time.mktime(LocalTime.timetuple())
    utcTime = datetime.datetime.utcfromtimestamp(EpochSecond)

    return utcTime

>>> LocalTime = datetime.datetime.now()

>>> UTCTime = Local2UTC(LocalTime)

>>> LocalTime.ctime()

'Thu Feb  3 22:33:46 2011'

>>> UTCTime.ctime()

'Fri Feb  4 05:33:46 2011'

回答 9

如果您更喜欢datetime.datetime:

dt = datetime.strptime("2008-09-17 14:04:00","%Y-%m-%d %H:%M:%S")
utc_struct_time = time.gmtime(time.mktime(dt.timetuple()))
utc_dt = datetime.fromtimestamp(time.mktime(utc_struct_time))
print dt.strftime("%Y-%m-%d %H:%M:%S")

if you prefer datetime.datetime:

dt = datetime.strptime("2008-09-17 14:04:00","%Y-%m-%d %H:%M:%S")
utc_struct_time = time.gmtime(time.mktime(dt.timetuple()))
utc_dt = datetime.fromtimestamp(time.mktime(utc_struct_time))
print dt.strftime("%Y-%m-%d %H:%M:%S")

回答 10

简单

我这样做是这样的:

>>> utc_delta = datetime.utcnow()-datetime.now()
>>> utc_time = datetime(2008, 9, 17, 14, 2, 0) + utc_delta
>>> print(utc_time)
2008-09-17 19:01:59.999996

花式实施

如果想花哨的话,可以将其变成仿函数:

class to_utc():
    utc_delta = datetime.utcnow() - datetime.now()

    def __call__(cls, t):
        return t + cls.utc_delta

结果:

>>> utc_converter = to_utc()
>>> print(utc_converter(datetime(2008, 9, 17, 14, 2, 0)))
2008-09-17 19:01:59.999996

Simple

I did it like this:

>>> utc_delta = datetime.utcnow()-datetime.now()
>>> utc_time = datetime(2008, 9, 17, 14, 2, 0) + utc_delta
>>> print(utc_time)
2008-09-17 19:01:59.999996

Fancy Implementation

If you want to get fancy, you can turn this into a functor:

class to_utc():
    utc_delta = datetime.utcnow() - datetime.now()

    def __call__(cls, t):
        return t + cls.utc_delta

Result:

>>> utc_converter = to_utc()
>>> print(utc_converter(datetime(2008, 9, 17, 14, 2, 0)))
2008-09-17 19:01:59.999996

回答 11

您可以执行以下操作:

>>> from time import strftime, gmtime, localtime
>>> strftime('%H:%M:%S', gmtime()) #UTC time
>>> strftime('%H:%M:%S', localtime()) # localtime

You can do it with:

>>> from time import strftime, gmtime, localtime
>>> strftime('%H:%M:%S', gmtime()) #UTC time
>>> strftime('%H:%M:%S', localtime()) # localtime

回答 12

怎么样 –

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

如果以秒为单位None,则将本地时间转换为UTC时间,否则将传入的时间转换为UTC。

How about –

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

if seconds is None then it converts the local time to UTC time else converts the passed in time to UTC.


回答 13

用于避开日光节约等。

上述答案都没有特别帮助我。以下代码适用于GMT。

def get_utc_from_local(date_time, local_tz=None):
    assert date_time.__class__.__name__ == 'datetime'
    if local_tz is None:
        local_tz = pytz.timezone(settings.TIME_ZONE) # Django eg, "Europe/London"
    local_time = local_tz.normalize(local_tz.localize(date_time))
    return local_time.astimezone(pytz.utc)

import pytz
from datetime import datetime

summer_11_am = datetime(2011, 7, 1, 11)
get_utc_from_local(summer_11_am)
>>>datetime.datetime(2011, 7, 1, 10, 0, tzinfo=<UTC>)

winter_11_am = datetime(2011, 11, 11, 11)
get_utc_from_local(winter_11_am)
>>>datetime.datetime(2011, 11, 11, 11, 0, tzinfo=<UTC>)

For getting around day-light saving, etc.

None of the above answers particularly helped me. The code below works for GMT.

def get_utc_from_local(date_time, local_tz=None):
    assert date_time.__class__.__name__ == 'datetime'
    if local_tz is None:
        local_tz = pytz.timezone(settings.TIME_ZONE) # Django eg, "Europe/London"
    local_time = local_tz.normalize(local_tz.localize(date_time))
    return local_time.astimezone(pytz.utc)

import pytz
from datetime import datetime

summer_11_am = datetime(2011, 7, 1, 11)
get_utc_from_local(summer_11_am)
>>>datetime.datetime(2011, 7, 1, 10, 0, tzinfo=<UTC>)

winter_11_am = datetime(2011, 11, 11, 11)
get_utc_from_local(winter_11_am)
>>>datetime.datetime(2011, 11, 11, 11, 0, tzinfo=<UTC>)

回答 14

使用http://crsmithdev.com/arrow/

arrowObj = arrow.Arrow.strptime('2017-02-20 10:00:00', '%Y-%m-%d %H:%M:%S' , 'US/Eastern')

arrowObj.to('UTC') or arrowObj.to('local') 

这个图书馆让生活变得轻松:)

Using http://crsmithdev.com/arrow/

arrowObj = arrow.Arrow.strptime('2017-02-20 10:00:00', '%Y-%m-%d %H:%M:%S' , 'US/Eastern')

arrowObj.to('UTC') or arrowObj.to('local') 

This library makes life easy :)


回答 15

我在这里找到了另一个问题的最佳答案。它仅使用python内置库,不需要您输入本地时区(在我的情况下是要求)

import time
import calendar

local_time = time.strptime("2018-12-13T09:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
local_seconds = time.mktime(local_time)
utc_time = time.gmtime(local_seconds)

我在此重新发布答案,因为此问题会在Google中弹出,而不是根据搜索关键字在链接的问题中弹出。

I found the best answer on another question here. It only uses python built-in libraries and does not require you to input your local timezone (a requirement in my case)

import time
import calendar

local_time = time.strptime("2018-12-13T09:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
local_seconds = time.mktime(local_time)
utc_time = time.gmtime(local_seconds)

I’m reposting the answer here since this question pops up in google instead of the linked question depending on the search keywords.


回答 16

我的一个项目中有以下代码:

from datetime import datetime
## datetime.timezone works in newer versions of python
try:
    from datetime import timezone
    utc_tz = timezone.utc
except:
    import pytz
    utc_tz = pytz.utc

def _to_utc_date_string(ts):
    # type (Union[date,datetime]]) -> str
    """coerce datetimes to UTC (assume localtime if nothing is given)"""
    if (isinstance(ts, datetime)):
        try:
            ## in python 3.6 and higher, ts.astimezone() will assume a
            ## naive timestamp is localtime (and so do we)
            ts = ts.astimezone(utc_tz)
        except:
            ## in python 2.7 and 3.5, ts.astimezone() will fail on
            ## naive timestamps, but we'd like to assume they are
            ## localtime
            import tzlocal
            ts = tzlocal.get_localzone().localize(ts).astimezone(utc_tz)
    return ts.strftime("%Y%m%dT%H%M%SZ")

I have this code in one of my projects:

from datetime import datetime
## datetime.timezone works in newer versions of python
try:
    from datetime import timezone
    utc_tz = timezone.utc
except:
    import pytz
    utc_tz = pytz.utc

def _to_utc_date_string(ts):
    # type (Union[date,datetime]]) -> str
    """coerce datetimes to UTC (assume localtime if nothing is given)"""
    if (isinstance(ts, datetime)):
        try:
            ## in python 3.6 and higher, ts.astimezone() will assume a
            ## naive timestamp is localtime (and so do we)
            ts = ts.astimezone(utc_tz)
        except:
            ## in python 2.7 and 3.5, ts.astimezone() will fail on
            ## naive timestamps, but we'd like to assume they are
            ## localtime
            import tzlocal
            ts = tzlocal.get_localzone().localize(ts).astimezone(utc_tz)
    return ts.strftime("%Y%m%dT%H%M%SZ")

回答 17

在python3中:

pip install python-dateutil

from dateutil.parser import tz

mydt.astimezone(tz.gettz('UTC')).replace(tzinfo=None) 

In python3:

pip install python-dateutil

from dateutil.parser import tz

mydt.astimezone(tz.gettz('UTC')).replace(tzinfo=None) 

回答 18

怎么样 –

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

如果以秒为单位None,则将本地时间转换为UTC时间,否则将传入的时间转换为UTC。

How about –

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

if seconds is None then it converts the local time to UTC time else converts the passed in time to UTC.


Argparse:在“ –help”中包含默认值的方法吗?

问题:Argparse:在“ –help”中包含默认值的方法吗?

假设我有以下argparse代码段:

diags.cmdln_parser.add_argument( '--scan-time',
                     action  = 'store',
                     nargs   = '?',
                     type    = int,
                     default = 5,
                     help    = "Wait SCAN-TIME seconds between status checks.")

当前,--help返回:

usage: connection_check.py [-h]
                             [--version] [--scan-time [SCAN_TIME]]

          Test the reliability/uptime of a connection.



optional arguments:
-h, --help            show this help message and exit
--version             show program's version number and exit
--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.

我更喜欢这样的东西:

--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.
                    (Default = 5)

偷看帮助格式化程序代码,发现选择有限。是否有一种巧妙的方法来argparse--scan-time类似的方式打印默认值,还是我应该只是help格式化程序的子类?

Suppose I have the following argparse snippet:

diags.cmdln_parser.add_argument( '--scan-time',
                     action  = 'store',
                     nargs   = '?',
                     type    = int,
                     default = 5,
                     help    = "Wait SCAN-TIME seconds between status checks.")

Currently, --help returns:

usage: connection_check.py [-h]
                             [--version] [--scan-time [SCAN_TIME]]

          Test the reliability/uptime of a connection.



optional arguments:
-h, --help            show this help message and exit
--version             show program's version number and exit
--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.

I would prefer something like:

--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.
                    (Default = 5)

Peeking at the help formatter code revealed limited options. Is there a clever way to get argparse to print the default value for --scan-time in a similar fashion, or should I just subclass the help formatter?


回答 0

使用argparse.ArgumentDefaultsHelpFormatter格式化程序

parser = argparse.ArgumentParser(
    # ... other options ...
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

引用文档:

另一个可用的格式化程序类ArgumentDefaultsHelpFormatter,将添加有关每个参数的默认值的信息。

请注意,这仅适用于已定义帮助文本的参数;如果没有help参数值,则没有帮助消息将有关默认值的信息添加到中

然后,您的扫描时间选项的确切输出将变为:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)

Use the argparse.ArgumentDefaultsHelpFormatter formatter:

parser = argparse.ArgumentParser(
    # ... other options ...
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

To quote the documentation:

The other formatter class available, ArgumentDefaultsHelpFormatter, will add information about the default value of each of the arguments.

Note that this only applies to arguments that have help text defined; with no help value for an argument, there is no help message to add information about the default value to.

The exact output for your scan-time option then becomes:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)

回答 1

添加'%(default)s'到帮助参数以控制显示内容。

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")

Add '%(default)s' to the help parameter to control what is displayed.

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")

回答 2

包装类

这是迄今为止我发现的最可靠,最干的方法,既可以显示默认值,也可以同时使用另一个格式化程序argparse.RawTextHelpFormatter

#!/usr/bin/env python3

import argparse

class ArgumentParserWithDefaults(argparse.ArgumentParser):
    def add_argument(self, *args, help=None, default=None, **kwargs):
        if help is not None:
            kwargs['help'] = help
        if default is not None and args[0] != '-h':
            kwargs['default'] = default
            if help is not None:
                kwargs['help'] += ' Default: {}'.format(default)
        super().add_argument(*args, **kwargs)

parser = ArgumentParserWithDefaults(
    formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.add_argument('--no-default', help='''my help
for no-default''')
parser.add_argument('--no-help', default=101)

parser.print_help()
print()
print(parser.parse_args())

输出:

usage: main.py [-h] [-a A] [-b B] [--no-default NO_DEFAULT]
               [--no-help NO_HELP]

optional arguments:
  -h, --help            show this help message and exit
  -a A                  my help
                        for a Default: 13
  -b B                  my help
                        for b Default: 42
  --no-default NO_DEFAULT
                        my help
                        for no-default
  --no-help NO_HELP

Namespace(a=13, b=42, no_default=None, no_help=101)

ArgumentDefaultsHelpFormatter+ RawTextHelpFormatter多重继承

多重继承可以正常工作,但它似乎不是公共API:

#!/usr/bin/env python3

import argparse

class RawTextArgumentDefaultsHelpFormatter(
        argparse.ArgumentDefaultsHelpFormatter,
        argparse.RawTextHelpFormatter
    ):
        pass

parser = argparse.ArgumentParser(
    formatter_class=RawTextArgumentDefaultsHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.print_help()

输出:

usage: a.py [-h] [-a A] [-b B]

optional arguments:
  -h, --help  show this help message and exit
  -a A        my help
              for a (default: 13)
  -b B        my help
              for b (default: 42)

它之所以有效,是因为我们可以从https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648的源代码中轻松地看到:

  • RawTextHelpFormatter 实施 _split_lines
  • ArgumentDefaultsHelpFormatter 实施 _get_help_string

因此我们可以猜测它们会一起正常工作。

但是,这似乎不是公共API,也不是的方法formatter_class,因此我认为目前尚无公共API方法。argparsedocstring说:

本模块中的所有其他类均视为实现细节。(还要注意,仅将HelpFormatter和RawDescriptionHelpFormatter视为对象名称是公共的-格式化程序对象的API仍被视为实现细节。)

另请参阅:自定义argparse帮助消息

在Python 3.6.5上测试。

Wrapper class

This is the most reliable and DRY approach I’ve found so far to both show defaults and use another formatter such as argparse.RawTextHelpFormatter at the same time:

#!/usr/bin/env python3

import argparse

class ArgumentParserWithDefaults(argparse.ArgumentParser):
    def add_argument(self, *args, help=None, default=None, **kwargs):
        if help is not None:
            kwargs['help'] = help
        if default is not None and args[0] != '-h':
            kwargs['default'] = default
            if help is not None:
                kwargs['help'] += ' Default: {}'.format(default)
        super().add_argument(*args, **kwargs)

parser = ArgumentParserWithDefaults(
    formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.add_argument('--no-default', help='''my help
for no-default''')
parser.add_argument('--no-help', default=101)

parser.print_help()
print()
print(parser.parse_args())

Output:

usage: main.py [-h] [-a A] [-b B] [--no-default NO_DEFAULT]
               [--no-help NO_HELP]

optional arguments:
  -h, --help            show this help message and exit
  -a A                  my help
                        for a Default: 13
  -b B                  my help
                        for b Default: 42
  --no-default NO_DEFAULT
                        my help
                        for no-default
  --no-help NO_HELP

Namespace(a=13, b=42, no_default=None, no_help=101)

ArgumentDefaultsHelpFormatter + RawTextHelpFormatter multiple inheritance

Multiple inheritance just works, but it does not seem to be public API:

#!/usr/bin/env python3

import argparse

class RawTextArgumentDefaultsHelpFormatter(
        argparse.ArgumentDefaultsHelpFormatter,
        argparse.RawTextHelpFormatter
    ):
        pass

parser = argparse.ArgumentParser(
    formatter_class=RawTextArgumentDefaultsHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.print_help()

Output:

usage: a.py [-h] [-a A] [-b B]

optional arguments:
  -h, --help  show this help message and exit
  -a A        my help
              for a (default: 13)
  -b B        my help
              for b (default: 42)

It just works works because as we can see trivially from the sources https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648 that:

  • RawTextHelpFormatter implements _split_lines
  • ArgumentDefaultsHelpFormatter implements _get_help_string

so we can guess that they will work together just fine.

However, this does not seem to be public API, and neither are the methods of formatter_class, so I don’t think there is a public API way to do it currently. argparse docstring says:

All other classes in this module are considered implementation details. (Also note that HelpFormatter and RawDescriptionHelpFormatter are only considered public as object names — the API of the formatter objects is still considered an implementation detail.)

See also: Customize argparse help message

Tested on Python 3.6.5.


动态打印一行

问题:动态打印一行

我想做几条给出标准输出的语句,但不要在语句之间看到换行符。

具体来说,假设我有:

for item in range(1,100):
    print item

结果是:

1
2
3
4
.
.
.

如何使它看起来像:

1 2 3 4 5 ...

更妙的是,是否可以打印单号最后一个号码,所以只有一个号码在屏幕上在同一时间?

I would like to make several statements that give standard output without seeing newlines in between statements.

Specifically, suppose I have:

for item in range(1,100):
    print item

The result is:

1
2
3
4
.
.
.

How get this to instead look like:

1 2 3 4 5 ...

Even better, is it possible to print the single number over the last number, so only one number is on the screen at a time?


回答 0

更改print item为:

  • print item, 在Python 2.7中
  • print(item, end=" ") 在Python 3中

如果要动态打印数据,请使用以下语法:

  • print(item, sep=' ', end='', flush=True) 在Python 3中

Change print item to:

  • print item, in Python 2.7
  • print(item, end=" ") in Python 3

If you want to print the data dynamically use following syntax:

  • print(item, sep=' ', end='', flush=True) in Python 3

回答 1

顺便说一句……如何每次都刷新它以便它在一个地方打印mi只需更改数字。

通常,这样做的方法是使用终端控制代码。这是一个非常简单的情况,对于该情况,您只需要一个特殊字符:用'\r'Python(和许多其他语言)编写的U + 000D CARRIAGE RETURN 。这是一个基于您的代码的完整示例:

from sys import stdout
from time import sleep
for i in range(1,20):
    stdout.write("\r%d" % i)
    stdout.flush()
    sleep(1)
stdout.write("\n") # move the cursor to the next line

关于此的一些事情可能令人惊讶:

  • \r去的字符串,这样的开始,程序运行时,光标会一直在数字后。这不只是装饰性的:如果您反过来做的话,某些终端仿真器会非常混乱。
  • 如果您不包括最后一行,则在程序终止后,您的外壳程序将在数字的顶部显示其提示。
  • stdout.flush在某些系统上,这是必需的,否则您将不会获得任何输出。其他系统可能不需要它,但是它没有任何危害。

如果您发现这不起作用,那么您首先应该怀疑的是您的终端仿真器有问题。该vttest程序可以帮助你测试。

你可以更换stdout.write一个print声明,但我宁愿不要混淆print与直接使用的文件对象。

By the way…… How to refresh it every time so it print mi in one place just change the number.

In general, the way to do that is with terminal control codes. This is a particularly simple case, for which you only need one special character: U+000D CARRIAGE RETURN, which is written '\r' in Python (and many other languages). Here’s a complete example based on your code:

from sys import stdout
from time import sleep
for i in range(1,20):
    stdout.write("\r%d" % i)
    stdout.flush()
    sleep(1)
stdout.write("\n") # move the cursor to the next line

Some things about this that may be surprising:

  • The \r goes at the beginning of the string so that, while the program is running, the cursor will always be after the number. This isn’t just cosmetic: some terminal emulators get very confused if you do it the other way around.
  • If you don’t include the last line, then after the program terminates, your shell will print its prompt on top of the number.
  • The stdout.flush is necessary on some systems, or you won’t get any output. Other systems may not require it, but it doesn’t do any harm.

If you find that this doesn’t work, the first thing you should suspect is that your terminal emulator is buggy. The vttest program can help you test it.

You could replace the stdout.write with a print statement but I prefer not to mix print with direct use of file objects.


回答 2

使用print item,使打印语句忽略换行符。

在Python 3中为print(item, end=" ")

如果希望每个数字都显示在同一位置,请使用示例(Python 2.7):

to = 20
digits = len(str(to - 1))
delete = "\b" * (digits + 1)
for i in range(to):
    print "{0}{1:{2}}".format(delete, i, digits),

在Python 3中,它有点复杂。在这里,您需要刷新,sys.stdout否则在循环完成之前它不会打印任何内容:

import sys
to = 20
digits = len(str(to - 1))
delete = "\b" * (digits)
for i in range(to):
   print("{0}{1:{2}}".format(delete, i, digits), end="")
   sys.stdout.flush()

Use print item, to make the print statement omit the newline.

In Python 3, it’s print(item, end=" ").

If you want every number to display in the same place, use for example (Python 2.7):

to = 20
digits = len(str(to - 1))
delete = "\b" * (digits + 1)
for i in range(to):
    print "{0}{1:{2}}".format(delete, i, digits),

In Python 3, it’s a bit more complicated; here you need to flush sys.stdout or it won’t print anything until after the loop has finished:

import sys
to = 20
digits = len(str(to - 1))
delete = "\b" * (digits)
for i in range(to):
   print("{0}{1:{2}}".format(delete, i, digits), end="")
   sys.stdout.flush()

回答 3

与其他示例一样,
我使用类似的方法,而不是花时间计算出最后的输出长度,等等,

我只是使用ANSI代码转义符移回到行的开头,然后在打印我的当前状态输出之前清除整行。

import sys

class Printer():
    """Print things to stdout on one line dynamically"""
    def __init__(self,data):
        sys.stdout.write("\r\x1b[K"+data.__str__())
        sys.stdout.flush()

要在迭代循环中使用,您只需调用以下内容:

x = 1
for f in fileList:
    ProcessFile(f)
    output = "File number %d completed." % x
    Printer(output)
    x += 1   

在这里查看更多

Like the other examples,
I use a similar approach but instead of spending time calculating out the last output length, etc,

I simply use ANSI code escapes to move back to the beginning of the line and then clear that entire line before printing my current status output.

import sys

class Printer():
    """Print things to stdout on one line dynamically"""
    def __init__(self,data):
        sys.stdout.write("\r\x1b[K"+data.__str__())
        sys.stdout.flush()

To use in your iteration loop you would just call something like:

x = 1
for f in fileList:
    ProcessFile(f)
    output = "File number %d completed." % x
    Printer(output)
    x += 1   

See more here


回答 4

您可以在打印语句中添加尾随逗号,以在每次迭代中打印空格而不是换行符:

print item,

另外,如果您使用的是Python 2.6或更高版本,则可以使用新的打印功能,该功能可以让您指定在要打印的每个项目的末尾甚至都不应该有空格(或者允许您指定要结束的任何位置)想):

from __future__ import print_function
...
print(item, end="")

最后,您可以通过从sys模块导入标准输出直接写入标准输出,该模块返回一个类似文件的对象:

from sys import stdout
...
stdout.write( str(item) )

You can add a trailing comma to your print statement to print a space instead of a newline in each iteration:

print item,

Alternatively, if you’re using Python 2.6 or later, you can use the new print function, which would allow you to specify that not even a space should come at the end of each item being printed (or allow you to specify whatever end you want):

from __future__ import print_function
...
print(item, end="")

Finally, you can write directly to standard output by importing it from the sys module, which returns a file-like object:

from sys import stdout
...
stdout.write( str(item) )

回答 5

更改

print item

print "\033[K", item, "\r",
sys.stdout.flush()
  • “ \ 033 [K”清除到行尾
  • \ r,返回到行的开头
  • flush语句确保它立即显示,以便您获得实时输出。

change

print item

to

print "\033[K", item, "\r",
sys.stdout.flush()
  • “\033[K” clears to the end of the line
  • the \r, returns to the beginning of the line
  • the flush statement makes sure it shows up immediately so you get real-time output.

回答 6

我认为一个简单的连接应该起作用:

nl = []
for x in range(1,10):nl.append(str(x))
print ' '.join(nl)

I think a simple join should work:

nl = []
for x in range(1,10):nl.append(str(x))
print ' '.join(nl)

回答 7

我在2.7上使用的另一个答案是仅打印“。”。每次循环运行(向用户表明事情还在运行)是这样的:

print "\b.",

打印“。” 每个字符之间没有空格。看起来更好一点,并且效果很好。\ b是那些想知道的退格字符。

Another answer that I’m using on 2.7 where I’m just printing out a “.” every time a loop runs (to indicate to the user that things are still running) is this:

print "\b.",

It prints the “.” characters without spaces between each. It looks a little better and works pretty well. The \b is a backspace character for those wondering.


回答 8

这么多复杂的答案。如果您拥有python 3,只需将其放在\r打印开始处,然后添加end='', flush=True到其中:

import time

for i in range(10):
    print(f'\r{i} foo bar', end='', flush=True)
    time.sleep(0.5)

这将原位写入0 foo bar,然后1 foo bar依此类推。

So many complicated answers. If you have python 3, simply put \r at the start of the print, and add end='', flush=True to it:

import time

for i in range(10):
    print(f'\r{i} foo bar', end='', flush=True)
    time.sleep(0.5)

This will write 0 foo bar, then 1 foo bar etc, in-place.


回答 9

要使数字彼此覆盖,可以执行以下操作:

for i in range(1,100):
    print "\r",i,

只要在第一列中打印该数字,它就应该起作用。

编辑:这是一个即使没有在第一栏中打印也可以使用的版本。

prev_digits = -1
for i in range(0,1000):
    print("%s%d" % ("\b"*(prev_digits + 1), i)),
    prev_digits = len(str(i))

我应该注意,此代码已经过测试,并且可以在Windows的Windows 2.5的WIndows控制台中正常运行。根据另一些说法,可能需要刷新stdout才能看到结果。YMMV。

To make the numbers overwrite each other, you can do something like this:

for i in range(1,100):
    print "\r",i,

That should work as long as the number is printed in the first column.

EDIT: Here’s a version that will work even if it isn’t printed in the first column.

prev_digits = -1
for i in range(0,1000):
    print("%s%d" % ("\b"*(prev_digits + 1), i)),
    prev_digits = len(str(i))

I should note that this code was tested and works just fine in Python 2.5 on Windows, in the WIndows console. According to some others, flushing of stdout may be required to see the results. YMMV.


回答 10

“顺便说一下……如何每次都刷新它,以便它在一个地方打印mi只需更改数字即可。”

这确实是一个棘手的话题。什么扎克建议(输出控制台控制代码)是实现这一目标的方法之一。

您可以使用(n)个curses,但这主要适用于* nixes。

在Windows上(这是有趣的部分),它很少被提及(我不明白为什么),您可以将Python绑定到WinAPI(默认情况下还与ActivePython一起使用http://sourceforge.net/projects/pywin32/)-它不是努力工作,效果很好。这是一个小例子:

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    output_handle.WriteConsoleOutputCharacter( i, pos )
    time.sleep( 1 )

或者,如果要使用print(语句或函数,没有区别):

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    print i
    output_handle.SetConsoleCursorPosition( pos )
    time.sleep( 1 )

win32console 模块使您可以使用Windows控制台执行更多有趣的事情…我不是WinAPI的忠实拥护者,但是最近我意识到,至少有一半的反对意见是由用C编写WinAPI代码引起的-pythonic绑定是更容易使用。

当然,所有其他答案都是不错的,而且是Python语言的,但是…如果我想在一行中打印怎么办?还是写多行文本,而不是清除并重新写相同的行?我的解决方案使这成为可能。

“By the way…… How to refresh it every time so it print mi in one place just change the number.”

It’s really tricky topic. What zack suggested ( outputting console control codes ) is one way to achieve that.

You can use (n)curses, but that works mainly on *nixes.

On Windows (and here goes interesting part) which is rarely mentioned (I can’t understand why) you can use Python bindings to WinAPI (http://sourceforge.net/projects/pywin32/ also with ActivePython by default) – it’s not that hard and works well. Here’s a small example:

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    output_handle.WriteConsoleOutputCharacter( i, pos )
    time.sleep( 1 )

Or, if you want to use print (statement or function, no difference):

import win32console, time

output_handle = win32console.GetStdHandle(  win32console.STD_OUTPUT_HANDLE )
info = output_handle.GetConsoleScreenBufferInfo()
pos = info["CursorPosition"]

for i in "\\|/-\\|/-":
    print i
    output_handle.SetConsoleCursorPosition( pos )
    time.sleep( 1 )

win32console module enables you to do many more interesting things with windows console… I’m not a big fan of WinAPI, but recently I realized that at least half of my antipathy towards it was caused by writing WinAPI code in C – pythonic bindings are much easier to use.

All other answers are great and pythonic, of course, but… What if I wanted to print on previous line? Or write multiline text, than clear it and write the same lines again? My solution makes that possible.


回答 11

对于Python 2.7

for x in range(0, 3):
    print x,

对于Python 3

for x in range(0, 3):
    print(x, end=" ")

for Python 2.7

for x in range(0, 3):
    print x,

for Python 3

for x in range(0, 3):
    print(x, end=" ")

回答 12

In [9]: print?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function print>
Namespace:      Python builtin
Docstring:
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep:  string inserted between values, default a space.
end:  string appended after the last value, default a newline.
In [9]: print?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function print>
Namespace:      Python builtin
Docstring:
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep:  string inserted between values, default a space.
end:  string appended after the last value, default a newline.

回答 13

如果只想打印数字,则可以避免循环。

# python 3
import time

startnumber = 1
endnumber = 100

# solution A without a for loop
start_time = time.clock()
m = map(str, range(startnumber, endnumber + 1))
print(' '.join(m))
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('took {0}ms\n'.format(timetaken))

# solution B: with a for loop
start_time = time.clock()
for i in range(startnumber, endnumber + 1):
    print(i, end=' ')
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('\ntook {0}ms\n'.format(timetaken))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100花费21.1986929975ms

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100花费491.466823551ms

If you just want to print the numbers, you can avoid the loop.

# python 3
import time

startnumber = 1
endnumber = 100

# solution A without a for loop
start_time = time.clock()
m = map(str, range(startnumber, endnumber + 1))
print(' '.join(m))
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('took {0}ms\n'.format(timetaken))

# solution B: with a for loop
start_time = time.clock()
for i in range(startnumber, endnumber + 1):
    print(i, end=' ')
end_time = time.clock()
timetaken = (end_time - start_time) * 1000
print('\ntook {0}ms\n'.format(timetaken))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 took 21.1986929975ms

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 took 491.466823551ms


回答 14

最好的方法是使用 \r角色

只需尝试以下代码:

import time
for n in range(500):
  print(n, end='\r')
  time.sleep(0.01)
print()  # start new line so most recently printed number stays

The best way to accomplish this is to use the \r character

Just try the below code:

import time
for n in range(500):
  print(n, end='\r')
  time.sleep(0.01)
print()  # start new line so most recently printed number stays

回答 15

在Python 3中,您可以这样操作:

for item in range(1,10):
    print(item, end =" ")

输出:

1 2 3 4 5 6 7 8 9 

元组:您可以对元组执行相同的操作:

tup = (1,2,3,4,5)

for n in tup:
    print(n, end = " - ")

输出:

1 - 2 - 3 - 4 - 5 - 

另一个例子:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for item in list_of_tuples:
    print(item)

输出:

(1, 2)
('A', 'B')
(3, 4)
('Cat', 'Dog')

您甚至可以像这样打开元组的包装:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]

# Tuple unpacking so that you can deal with elements inside of the tuple individually
for (item1, item2) in list_of_tuples:
    print(item1, item2)   

输出:

1 2
A B
3 4
Cat Dog

另一个变化:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for (item1, item2) in list_of_tuples:
    print(item1)
    print(item2)
    print('\n')

输出:

1
2


A
B


3
4


Cat
Dog

In Python 3 you can do it this way:

for item in range(1,10):
    print(item, end =" ")

Outputs:

1 2 3 4 5 6 7 8 9 

Tuple: You can do the same thing with a tuple:

tup = (1,2,3,4,5)

for n in tup:
    print(n, end = " - ")

Outputs:

1 - 2 - 3 - 4 - 5 - 

Another example:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for item in list_of_tuples:
    print(item)

Outputs:

(1, 2)
('A', 'B')
(3, 4)
('Cat', 'Dog')

You can even unpack your tuple like this:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]

# Tuple unpacking so that you can deal with elements inside of the tuple individually
for (item1, item2) in list_of_tuples:
    print(item1, item2)   

Outputs:

1 2
A B
3 4
Cat Dog

another variation:

list_of_tuples = [(1,2),('A','B'), (3,4), ('Cat', 'Dog')]
for (item1, item2) in list_of_tuples:
    print(item1)
    print(item2)
    print('\n')

Outputs:

1
2


A
B


3
4


Cat
Dog

回答 16

打印语句末尾的逗号会省略新行。

for i in xrange(1,100):
  print i,

但这不会覆盖。

A comma at the end of the print statement omits the new line.

for i in xrange(1,100):
  print i,

but this does not overwrite.


回答 17

对于那些像我一样挣扎的人,我想出了以下似乎在python 3.7.4和3.5.2中都适用的代码。

我将范围从100扩展到1,000,000,因为它运行非常快,您可能看不到输出。这是因为设置的一个副作用end='\r'是最终循环迭代会清除所有输出。需要更长的数量才能证明其有效。此结果可能并非在所有情况下都令人满意,但在我的情况下还不错,并且OP没有指定一种方法或另一种方法。您可以使用if语句来评估要迭代的数组的长度,从而避免这种情况。在我的案例中,使其工作的关键是将方括号"{}".format()。否则,它不会起作用。

以下应按原样工作:

#!/usr/bin/env python3

for item in range(1,1000000):
    print("{}".format(item), end='\r', flush=True)

For those struggling as I did, I came up with the following that appears to work in both python 3.7.4 and 3.5.2.

I expanded the range from 100 to 1,000,000 because it runs very fast and you may not see the output. This is because one side effect of setting end='\r' is that the final loop iteration clears all of the output. A longer number was needed to demonstrate that it works. This result may not be desirable in all cases, but was fine in mine, and OP didn’t specify one way or another. You could potentially circumvent this with an if statement that evaluates the length of the array being iterated over, etc. The key to get it working in my case was to couple the brackets "{}" with .format(). Otherwise, it didn’t work.

Below should work as-is:

#!/usr/bin/env python3

for item in range(1,1000000):
    print("{}".format(item), end='\r', flush=True)

回答 18

for item in range(1,100):
    if item==99:
        print(item,end='')
    else:
        print (item,end=',')

输出:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49, 50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74, 75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99

for item in range(1,100):
    if item==99:
        print(item,end='')
    else:
        print (item,end=',')

Output: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99


回答 19

或更简单:

import time
a = 0
while True:
    print (a, end="\r")
    a += 1
    time.sleep(0.1)

end="\r" 从第一张打印的开始[0:]开始覆盖。

Or even simpler:

import time
a = 0
while True:
    print (a, end="\r")
    a += 1
    time.sleep(0.1)

end="\r" will overwrite from the beginning [0:] of the first print.


为什么我们在Python中需要“ finally”子句?

问题:为什么我们在Python中需要“ finally”子句?

我不知道为什么我们需要finallytry...except...finally报表。我认为,此代码块

try:
    run_code1()
except TypeError:
    run_code2()
other_code()

使用finally以下命令与此相同:

try:
    run_code1()
except TypeError:
    run_code2()
finally:
    other_code()

我想念什么吗?

I am not sure why we need finally in try...except...finally statements. In my opinion, this code block

try:
    run_code1()
except TypeError:
    run_code2()
other_code()

is the same with this one using finally:

try:
    run_code1()
except TypeError:
    run_code2()
finally:
    other_code()

Am I missing something?


回答 0

如果您提早返回,会有所不同:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   # The finally block is run before the method returns
finally:
    other_code()

比较一下:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   

other_code()  # This doesn't get run if there's an exception.

可能导致差异的其他情况:

  • 如果在except块内引发异常。
  • 如果引发异常,run_code1()但不是TypeError
  • 其他控制流语句,例如continuebreak语句。

It makes a difference if you return early:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   # The finally block is run before the method returns
finally:
    other_code()

Compare to this:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   

other_code()  # This doesn't get run if there's an exception.

Other situations that can cause differences:

  • If an exception is thrown inside the except block.
  • If an exception is thrown in run_code1() but it’s not a TypeError.
  • Other control flow statements such as continue and break statements.

回答 1

您可以finally用来确保文件或资源被关闭或释放,而不管是否发生异常,即使您没有捕获到该异常也是如此。(或者,如果您没有捕获到该特定异常。)

myfile = open("test.txt", "w")

try:
    myfile.write("the Answer is: ")
    myfile.write(42)   # raises TypeError, which will be propagated to caller
finally:
    myfile.close()     # will be executed before TypeError is propagated

在此示例中,使用该with语句会更好,但是这种结构可以用于其他类型的资源。

几年后,我写了一篇博客文章,讲述滥用finally读者可能会觉得有趣的事情。

You can use finally to make sure files or resources are closed or released regardless of whether an exception occurs, even if you don’t catch the exception. (Or if you don’t catch that specific exception.)

myfile = open("test.txt", "w")

try:
    myfile.write("the Answer is: ")
    myfile.write(42)   # raises TypeError, which will be propagated to caller
finally:
    myfile.close()     # will be executed before TypeError is propagated

In this example you’d be better off using the with statement, but this kind of structure can be used for other kinds of resources.

A few years later, I wrote a blog post about an abuse of finally that readers may find amusing.


回答 2

它们不相等。不管其他什么情况发生,最终代码都会运行。这对于必须运行的清理代码很有用。

They are not equivalent. Finally code is run no matter what else happens. It is useful for cleanup code that has to run.


回答 3

除了上面的其他答案外,该finally子句无论执行什么都将else执行,而该子句仅在未引发异常的情况下才执行。

例如,无exceptions地写入文件将输出以下内容:

file = open('test.txt', 'w')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

输出:

Writing to file.
Write successful.
File closed.

如果有异常,代码将输出以下内容(请注意,故意使文件保持只读状态会导致错误。

file = open('test.txt', 'r')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

输出:

Could not write to file.
File closed.

我们可以看到,该finally子句无论有无异常都会执行。希望这可以帮助。

To add to the other answers above, the finally clause executes no matter what whereas the else clause executes only if an exception was not raised.

For example, writing to a file with no exceptions will output the following:

file = open('test.txt', 'w')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

OUTPUT:

Writing to file.
Write successful.
File closed.

If there is an exception, the code will output the following, (note that a deliberate error is caused by keeping the file read-only.

file = open('test.txt', 'r')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

OUTPUT:

Could not write to file.
File closed.

We can see that the finally clause executes regardless of an exception. Hope this helps.


回答 4

代码块不是等效的。finally如果run_code1()引发除以外的异常TypeError,或者run_code2()引发异常,则该子句也将运行,而other_code()在这些情况下,在第一个版本中则不会运行该子句。

The code blocks are not equivalent. The finally clause will also be run if run_code1() throws an exception other than TypeError, or if run_code2() throws an exception, while other_code() in the first version wouldn’t be run in these cases.


回答 5

在您的第一个示例中,如果run_code1()引发一个不是的异常会发生什么TypeError?… other_code()将不会被执行。

将其与finally:版本进行比较:other_code()保证无论是否引发任何异常都将被执行。

In your first example, what happens if run_code1() raises an exception that is not TypeError? … other_code() will not be executed.

Compare that with the finally: version: other_code() is guaranteed to be executed regardless of any exception being raised.


回答 6

文档中所述,该finally子句旨在定义在所有情况下都必须执行的清理操作。

如果finally存在,则指定“清理”处理程序。该try 子句被执行,包括any exceptelse子句。如果在任何子句中发生异常并且未进行处理,则将临时保存该异常。该finally子句被执行。如果存在已保存的异常,则会在finally 子句末重新引发。

一个例子:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

如您所见,该finally子句在任何情况下都会执行。在TypeError通过将两个字符串凸起不被处理except子句和后因此再次加注finally条款已经被执行。

在实际的应用程序中,无论是否成功使用资源,finally子句对于释放外部资源(例如文件或网络连接)都是有用的。

As explained in the documentation, the finally clause is intended to define clean-up actions that must be executed under all circumstances.

If finally is present, it specifies a ‘cleanup’ handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception it is re-raised at the end of the finally clause.

An example:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

As you can see, the finally clause is executed in any event. The TypeError raised by dividing two strings is not handled by the except clause and therefore re-raised after the finally clause has been executed.

In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.


回答 7

完美的例子如下:

try:
    #x = Hello + 20
    x = 10 + 20 
except:
    print 'I am in except block'
    x = 20 + 30
else:
    print 'I am in else block'
    x += 1
finally:
    print 'Finally x = %s' %(x)

Perfect example is as below:

try:
    #x = Hello + 20
    x = 10 + 20 
except:
    print 'I am in except block'
    x = 20 + 30
else:
    print 'I am in else block'
    x += 1
finally:
    print 'Finally x = %s' %(x)

回答 8

finally用于定义“清理动作”finally在离开try语句之前的任何事件中,无论是否发生异常(即使您不处理它),都将执行该子句。

我第二个@Byers的例子。

finally is for defining “clean up actions”. The finally clause is executed in any event before leaving the try statement, whether an exception (even if you do not handle it) has occurred or not.

I second @Byers’s example.


回答 9

当您要在运行主要工作的代码之前运行“可选”代码并且可选代码可能由于各种原因而失败时,也可以使用Final。

在下面的示例中,我们不确切知道store_some_debug_info可能会引发哪种异常。

我们可以运行:

try:
  store_some_debug_info()
except Exception:
  pass
do_something_really_important() 

但是,大多数的短毛猫都会抱怨捉摸不清一个exceptions。另外,由于我们选择仅pass针对错误,因此该except块并没有真正增加价值。

try:
  store_some_debug_info()
finally:
  do_something_really_important()     

上面的代码与第一个代码块具有相同的效果,但更为简洁。

Finally can also be used when you want to run “optional” code before running the code for your main work and that optional code may fail for various reasons.

In the following example, we don’t know precisely what kind of exceptions store_some_debug_info might throw.

We could run:

try:
  store_some_debug_info()
except Exception:
  pass
do_something_really_important() 

But, most linters will complain about catching too vague of an exception. Also, since we’re choosing to just pass for errors, the except block doesn’t really add value.

try:
  store_some_debug_info()
finally:
  do_something_really_important()     

The above code has the same effect as the 1st block of code but is more concise.


回答 10

几年来专业地使用delphi教会了我维护最终使用的清理例程。Delphi几乎会强制使用finally来清理在try块之前创建的所有资源,以免引起内存泄漏。这也是Java,Python和Ruby的工作方式。

resource = create_resource
try:
  use resource
finally:
  resource.cleanup

不管您在尝试和最终之间进行什么操作,资源都会被清理。另外,如果执行从未到达该try块,则不会清除它。(即create_resource本身引发异常),这使您的代码“异常安全”。

至于为什么您实际上需要一个finally块,并不是所有语言都需要。在C ++中,您自动调用了析构函数,这些析构函数在异常展开堆栈时强制执行清除。与尝试…最终的语言相比,我认为这是朝着更清洁的代码方向发展的一步。

{    
  type object1;
  smart_pointer<type> object1(new type());
} // destructors are automagically called here in LIFO order so no finally required.

Using delphi professionally for some years taught me to safeguard my cleanup routines using finally. Delphi pretty much enforces the use of finally to clean up any resources created before the try block, lest you cause a memory leak. This is also how Java, Python and Ruby works.

resource = create_resource
try:
  use resource
finally:
  resource.cleanup

and resource will be cleaned up regardless of what you do between try and finally. Also, it won’t be cleaned up if execution never reaches the try block. (i.e. create_resource itself throws an exception) It makes your code “exception safe”.

As to why you actually need a finally block, not all languages do. In C++ where you have automatically called destructors which enforce cleanup when an exception unrolls the stack. I think this is a step up in the direction of cleaner code compared to try…finally languages.

{    
  type object1;
  smart_pointer<type> object1(new type());
} // destructors are automagically called here in LIFO order so no finally required.

回答 11

一个try块只有一个强制性子句:try语句。else,else和finally子句是可选的,并且基于用户首选项。

最终:在Python离开try语句之前,它将在任何情况下在finally块中运行代码,即使它正在结束程序。例如,如果Python在except或else块中运行代码时遇到错误,则在停止程序之前,finally块仍将执行。

A try block has just one mandatory clause: The try statement. The except, else and finally clauses are optional and based on user preference.

finally: Before Python leaves the try statement, it will run the code in the finally block under any conditions, even if it’s ending the program. E.g., if Python ran into an error while running code in the except or else block, the finally block will still be executed before stopping the program.


回答 12

运行以下Python3代码以最终了解最终需求:

情况1:

count = 0
while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")
        finally:
            print("Your Attempts: {}".format(count))

案例2:

count = 0

while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")

        print("Your Attempts: {}".format(count))

每次尝试以下输入:

  1. 随机整数
  2. 正确的代码是586(尝试此操作,您将得到答案)
  3. 随机字符串

**在学习Python的初期。

Run these Python3 codes to watch the need of finally:

CASE1:

count = 0
while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")
        finally:
            print("Your Attempts: {}".format(count))

CASE2:

count = 0

while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")

        print("Your Attempts: {}".format(count))

Try the following inputs each time:

  1. random integers
  2. correct code which is 586(Try this and you will get your answer)
  3. random strings

** At a very early stage of learning Python.


回答 13

我试图在要阅读Excel工作表的地方运行代码。问题是,如果有一个没有工作表的文件说:SheetSum我无法将其移动到错误位置!我写的代码是:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets['df_1'] = pd.read_excel(open(data_file,'rb'), 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

给出错误:

[WinError 32]该进程无法访问文件,因为该文件正在被另一个进程使用

我必须添加完整的try except with finally块并告诉finally我在任何情况下都需要关闭文件:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets_file = open(data_file,'rb')
        sheets['df_1'] = pd.read_excel(sheets_file, 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    finally:
        sheets_file.close()
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

否则,文件仍然保持打开状态。

如果finally存在,则指定清除处理程序。该try 子句被执行,包括any exceptelse子句。如果在任何子句中发生异常并且未对其进行处理,则将临时保存异常。该finally子句被执行。如果存在已保存的异常,则会在finally 子句末重新引发。如果finally子句引发另一个异常,则将保存的异常设置为新异常的上下文。

..更多这里

I was trying to run a code where i wanted to read excel sheets. Issue was, if there is a file which has no sheet named say : SheetSum I am not able to move it to error location!! Code i wrote was:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets['df_1'] = pd.read_excel(open(data_file,'rb'), 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

Giving Error :

[WinError 32] The process cannot access the file because it is being used by another process

I had to add full try except with finally block and tell finally i need to close the file in any case like:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets_file = open(data_file,'rb')
        sheets['df_1'] = pd.read_excel(sheets_file, 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    finally:
        sheets_file.close()
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

Otherwise, file still remains open is the background.

If finally is present, it specifies a cleanup handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception it is re-raised at the end of the finally clause. If the finally clause raises another exception, the saved exception is set as the context of the new exception.

..More Here


将以2为底的二进制数字字符串转换为int

问题:将以2为底的二进制数字字符串转换为int

我只想将以2为底的二进制数字字符串转换为int,如下所示:

>>> '11111111'.fromBinaryToInt()
255

有没有办法在Python中做到这一点?

I’d simply like to convert a base-2 binary number string into an int, something like this:

>>> '11111111'.fromBinaryToInt()
255

Is there a way to do this in Python?


回答 0

您可以使用内置int函数,然后将输入数字的基数传递给它,即2二进制数:

>>> int('11111111', 2)
255

这是python2python3的文档。

You use the built-in int function, and pass it the base of the input number, i.e. 2 for a binary number:

>>> int('11111111', 2)
255

Here is documentation for python2, and for python3.


回答 1

只需在python交互界面中输入0b11111111

>>> 0b11111111
    255

Just type 0b11111111 in python interactive interface:

>>> 0b11111111
    255

回答 2

另一种方法是使用bitstring模块:

>>> from bitstring import BitArray
>>> b = BitArray(bin='11111111')
>>> b.uint
255

请注意,无符号整数与有符号整数不同:

>>> b.int
-1

bitstring模块不是必需的,但它具有许多高性能的方法,可以将输入转换为位或转换为其他形式,以及对其进行操作。

Another way to do this is by using the bitstring module:

>>> from bitstring import BitArray
>>> b = BitArray(bin='11111111')
>>> b.uint
255

Note that the unsigned integer is different from the signed integer:

>>> b.int
-1

The bitstring module isn’t a requirement, but it has lots of performant methods for turning input into and from bits into other forms, as well as manipulating them.


回答 3

将int与base一起使用是正确的方法。在发现int也需要基础之前,我曾经这样做过。从本质上讲,这是应用于将二进制转换为十进制的原始方法的列表理解的减少(例如110 = 2 ** 0 * 0 + 2 ** 1 * 1 + 2 ** 2 * 1)

add = lambda x,y : x + y
reduce(add, [int(x) * 2 ** y for x, y in zip(list(binstr), range(len(binstr) - 1, -1, -1))])

Using int with base is the right way to go. I used to do this before I found int takes base also. It is basically a reduce applied on a list comprehension of the primitive way of converting binary to decimal ( e.g. 110 = 2**0 * 0 + 2 ** 1 * 1 + 2 ** 2 * 1)

add = lambda x,y : x + y
reduce(add, [int(x) * 2 ** y for x, y in zip(list(binstr), range(len(binstr) - 1, -1, -1))])

回答 4

如果您想知道幕后发生的事情,那么您就可以开始了。

class Binary():
def __init__(self, binNumber):
    self._binNumber = binNumber
    self._binNumber = self._binNumber[::-1]
    self._binNumber = list(self._binNumber)
    self._x = [1]
    self._count = 1
    self._change = 2
    self._amount = 0
    print(self._ToNumber(self._binNumber))
def _ToNumber(self, number):
    self._number = number
    for i in range (1, len (self._number)):
        self._total = self._count * self._change
        self._count = self._total
        self._x.append(self._count)
    self._deep = zip(self._number, self._x)
    for self._k, self._v in self._deep:
        if self._k == '1':
            self._amount += self._v
    return self._amount
mo = Binary('101111110')

If you wanna know what is happening behind the scene, then here you go.

class Binary():
def __init__(self, binNumber):
    self._binNumber = binNumber
    self._binNumber = self._binNumber[::-1]
    self._binNumber = list(self._binNumber)
    self._x = [1]
    self._count = 1
    self._change = 2
    self._amount = 0
    print(self._ToNumber(self._binNumber))
def _ToNumber(self, number):
    self._number = number
    for i in range (1, len (self._number)):
        self._total = self._count * self._change
        self._count = self._total
        self._x.append(self._count)
    self._deep = zip(self._number, self._x)
    for self._k, self._v in self._deep:
        if self._k == '1':
            self._amount += self._v
    return self._amount
mo = Binary('101111110')

回答 5

递归Python实现:

def int2bin(n):
    return int2bin(n >> 1) + [n & 1] if n > 1 else [1] 

A recursive Python implementation:

def int2bin(n):
    return int2bin(n >> 1) + [n & 1] if n > 1 else [1] 

回答 6

如果您使用的是python3.6或更高版本,则可以使用f-string进行转换:

二进制到十进制:

>>> print(f'{0b1011010:#0}')
90

>>> bin_2_decimal = int(f'{0b1011010:#0}')
>>> bin_2_decimal
90

二进制到八进制六进制等

>>> f'{0b1011010:#o}'
'0o132'  # octal

>>> f'{0b1011010:#x}'
'0x5a'   # hexadecimal

>>> f'{0b1011010:#0}'
'90'     # decimal

注意2条以冒号分隔的信息。

这样,您可以通过更改冒号右侧来在{二进制,八进制,十六进制,十进制}之间转换为{二进制,八进制,十六进制,十进制}。

:#b -> converts to binary
:#o -> converts to octal
:#x -> converts to hexadecimal 
:#0 -> converts to decimal as above example

尝试将冒号的左侧更改为八进制/十六进制/十进制。

If you are using python3.6 or later you can use f-string to do the conversion:

Binary to decimal:

>>> print(f'{0b1011010:#0}')
90

>>> bin_2_decimal = int(f'{0b1011010:#0}')
>>> bin_2_decimal
90

binary to octal hexa and etc.

>>> f'{0b1011010:#o}'
'0o132'  # octal

>>> f'{0b1011010:#x}'
'0x5a'   # hexadecimal

>>> f'{0b1011010:#0}'
'90'     # decimal

Pay attention to 2 piece of information separated by colon.

In this way, you can convert between {binary, octal, hexadecimal, decimal} to {binary, octal, hexadecimal, decimal} by changing right side of colon[:]

:#b -> converts to binary
:#o -> converts to octal
:#x -> converts to hexadecimal 
:#0 -> converts to decimal as above example

Try changing left side of colon to have octal/hexadecimal/decimal.


回答 7

对于较大的矩阵(10 ** 5行及以上),最好使用矢量化matmult。一杆传入所有行和列。非常快。python中没有循环。我最初将其设计为将许多二进制列(例如MovieLens中10个不同类型列的0/1)转换为每个示例行的单个整数。

def BitsToIntAFast(bits):
  m,n = bits.shape
  a = 2**np.arange(n)[::-1]  # -1 reverses array of powers of 2 of same length as bits
  return bits @ a

For large matrix (10**5 rows and up) it is better to use a vectorized matmult. Pass in all rows and cols in one shot. It is extremely fast. There is no looping in python here. I originally designed it for converting many binary columns like 0/1 for like 10 different genre columns in MovieLens into a single integer for each example row.

def BitsToIntAFast(bits):
  m,n = bits.shape
  a = 2**np.arange(n)[::-1]  # -1 reverses array of powers of 2 of same length as bits
  return bits @ a

Python图像库失败,并显示消息“解码器JPEG不可用”-PIL

问题:Python图像库失败,并显示消息“解码器JPEG不可用”-PIL

PIL在我的系统中确实支持JPEG。

每当我上传时,我的代码都会失败并显示以下内容:

File "PIL/Image.py", line 375, in _getdecoder
    raise IOError("decoder %s not available" % decoder_name)
IOError: decoder jpeg not available

我该如何解决?

PIL does support JPEG in my system.

Whenever I do an upload, my code is failing with:

File "PIL/Image.py", line 375, in _getdecoder
    raise IOError("decoder %s not available" % decoder_name)
IOError: decoder jpeg not available

How can I resolve this?


回答 0

需要libjpeg-dev才能处理带有枕头(或PIL)的jpeg,因此您需要先安装它,然后重新编译枕头。在Ubuntu 14.04上似乎还需要libjpeg8-dev

如果您仍在使用PIL,那么这些天确实应该使用枕头,因此pip uninstall PIL请先遵循以下说明进行切换,或者如果您有充分的理由坚持使用PIL,请在下面将“枕头”替换为“ PIL” )。

在Ubuntu上:

# install libjpeg-dev with apt
sudo apt-get install libjpeg-dev
# if you're on Ubuntu 14.04, also install this
sudo apt-get install libjpeg8-dev

# reinstall pillow
pip install --no-cache-dir -I pillow

如果这不起作用,请根据您使用的是64位还是32位Ubuntu,尝试以下操作之一。

对于Ubuntu x64:

sudo ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libfreetype.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libz.so /usr/lib

或对于Ubuntu 32位:

sudo ln -s /usr/lib/i386-linux-gnu/libjpeg.so /usr/lib/
sudo ln -s /usr/lib/i386-linux-gnu/libfreetype.so.6 /usr/lib/
sudo ln -s /usr/lib/i386-linux-gnu/libz.so /usr/lib/

然后重新安装枕头:

pip install --no-cache-dir -I pillow

(进行编辑以包含来自评论的反馈。感谢Charles Offenbacher指出32位版本存在差异,而t-mart建议使用--no-cache-dir)。

libjpeg-dev is required to be able to process jpegs with pillow (or PIL), so you need to install it and then recompile pillow. It also seems that libjpeg8-dev is needed on Ubuntu 14.04

If you’re still using PIL then you should really be using pillow these days though, so first pip uninstall PIL before following these instructions to switch, or if you have a good reason for sticking with PIL then replace “pillow” with “PIL” in the below).

On Ubuntu:

# install libjpeg-dev with apt
sudo apt-get install libjpeg-dev
# if you're on Ubuntu 14.04, also install this
sudo apt-get install libjpeg8-dev

# reinstall pillow
pip install --no-cache-dir -I pillow

If that doesn’t work, try one of the below, depending on whether you are on 64bit or 32bit Ubuntu.

For Ubuntu x64:

sudo ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libfreetype.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libz.so /usr/lib

Or for Ubuntu 32bit:

sudo ln -s /usr/lib/i386-linux-gnu/libjpeg.so /usr/lib/
sudo ln -s /usr/lib/i386-linux-gnu/libfreetype.so.6 /usr/lib/
sudo ln -s /usr/lib/i386-linux-gnu/libz.so /usr/lib/

Then reinstall pillow:

pip install --no-cache-dir -I pillow

(Edits to include feedback from comments. Thanks Charles Offenbacher for pointing out this differs for 32bit, and t-mart for suggesting use of --no-cache-dir).


回答 1

对于OSX上的操作系统,我使用以下二进制文件来在系统范围内安装libpng和libjpeg:

适用于OSX的libpng和libjpeg

因为我已经安装了PIL(通过virtualenv上的pip),所以运行:

pip uninstall PIL
pip install PIL --upgrade

decoder JPEG not available为我解决了错误。

更新(4/24/14)

较新版本的pip需要附加标志才能从外部源下载库(包括PIL)。请尝试以下操作:

pip install PIL --allow-external PIL --allow-unverified PIL

有关其他信息,请参见以下答案:pip install PIL不要安装到virtualenv中

更新2

如果在OSX Mavericks上,则需要将ARCHFLAGS标志设置为@RicardoGonzales注释,如下所示

ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install PIL --allow-external PIL --allow-unverified PIL

For those on OSX, I used the following binary to get libpng and libjpeg installed systemwide:

libpng & libjpeg for OSX

Because I already had PIL installed (via pip on a virtualenv), I ran:

pip uninstall PIL
pip install PIL --upgrade

This resolved the decoder JPEG not available error for me.

UPDATE (4/24/14):

Newer versions of pip require additional flags to download libraries (including PIL) from external sources. Try the following:

pip install PIL --allow-external PIL --allow-unverified PIL

See the following answer for additional info: pip install PIL dont install into virtualenv

UPDATE 2:

If on OSX Mavericks, you’ll want to set the ARCHFLAGS flag as @RicardoGonzales comments below:

ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install PIL --allow-external PIL --allow-unverified PIL

回答 2

这是对我有用的唯一方法。安装软件包和重新安装PIL无效。

在ubuntu上,安装所需的软件包:

sudo apt-get install libjpeg-dev

(您可能还需要安装libfreetype6 libfreetype6-dev zlib1g-dev以启用其他解码器)。

然后用枕头更换PIL:

pip uninstall PIL
pip install pillow

This is the only way that worked for me. Installing packages and reinstalling PIL didn’t work.

On ubuntu, install the required package:

sudo apt-get install libjpeg-dev

(you may also want to install libfreetype6 libfreetype6-dev zlib1g-dev to enable other decoders).

Then replace PIL with pillow:

pip uninstall PIL
pip install pillow

回答 3

以下是在Ubuntu 12.04上的工作:

pip uninstall PIL
apt-get install libjpeg-dev
apt-get install libfreetype6-dev
apt-get install zlib1g-dev
apt-get install libpng12-dev
pip install PIL --upgrade

当您看到“-JPEG支持可用”时,表明它可以工作。

但是,如果在编辑jpeg图像时仍然不起作用,请检查python路径!我的python路径未命中/usr/local/lib/python2.7/dist-packages/PIL-1.1.7-py2.7-linux-x86_64.egg/,因此我~/.bashrc将以下代码添加到该文件中:

编辑: export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/dist-packages/PIL-1.1.7-py2.7-linux-x86_64.egg/

然后,终于可以了!!

The followed works on ubuntu 12.04:

pip uninstall PIL
apt-get install libjpeg-dev
apt-get install libfreetype6-dev
apt-get install zlib1g-dev
apt-get install libpng12-dev
pip install PIL --upgrade

when your see “– JPEG support avaliable” that means it works.

But, if it still doesn’t work when your edit your jpeg image, check the python path !! my python path missed /usr/local/lib/python2.7/dist-packages/PIL-1.1.7-py2.7-linux-x86_64.egg/, so I edit the ~/.bashrc add the following code to this file:

Edit: export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/dist-packages/PIL-1.1.7-py2.7-linux-x86_64.egg/

then, finally, it works!!


回答 4

在Fedora 17上,我必须先安装libjpeg-devel然后重新安装PIL

sudo yum install --assumeyes libjpeg-devel
sudo pip-python install --upgrade PIL

On Fedora 17 I had to install libjpeg-devel and afterwards reinstall PIL:

sudo yum install --assumeyes libjpeg-devel
sudo pip-python install --upgrade PIL

回答 5

Rolo的回答非常好,但是我不得不绕过pip缓存(pip 7引入)来重新安装Pillow,否则它将无法正确地重新编译!!!该命令是:

pip install -I --no-cache-dir -v Pillow

您可以通过在日志中读取以下内容来查看是否已正确配置枕头:

PIL SETUP SUMMARY
    --------------------------------------------------------------------
    version      Pillow 2.8.2
    platform     linux 3.4.3 (default, May 25 2015, 15:44:26)
                 [GCC 4.8.2]
    --------------------------------------------------------------------
    *** TKINTER support not available
    --- JPEG support available
    *** OPENJPEG (JPEG2000) support not available
    --- ZLIB (PNG/ZIP) support available
    --- LIBTIFF support available
    --- FREETYPE2 support available
    *** LITTLECMS2 support not available
    *** WEBP support not available
    *** WEBPMUX support not available
    --------------------------------------------------------------------

如您所见,启用了对jpg,tiff等的支持,因为我以前通过apt(libjpeg-dev libpng12-dev libfreetype6-dev libtiff-dev)安装了所需的库。

Rolo’s answer is excellent, however I had to reinstall Pillow by bypassing pip cache (introduced with pip 7) otherwise it won’t get properly recompiled!!! The command is:

pip install -I --no-cache-dir -v Pillow

and you can see if Pillow has been properly configured by reading in the logs this:

PIL SETUP SUMMARY
    --------------------------------------------------------------------
    version      Pillow 2.8.2
    platform     linux 3.4.3 (default, May 25 2015, 15:44:26)
                 [GCC 4.8.2]
    --------------------------------------------------------------------
    *** TKINTER support not available
    --- JPEG support available
    *** OPENJPEG (JPEG2000) support not available
    --- ZLIB (PNG/ZIP) support available
    --- LIBTIFF support available
    --- FREETYPE2 support available
    *** LITTLECMS2 support not available
    *** WEBP support not available
    *** WEBPMUX support not available
    --------------------------------------------------------------------

as you can see the support for jpg, tiff and so on is enabled, because I previously installed the required libraries via apt (libjpeg-dev libpng12-dev libfreetype6-dev libtiff-dev)


回答 6

在Mac OS X Mavericks(10.9.3)上,我通过执行以下操作解决了此问题:

通过brew安装libjpeg (软件包管理系统)

酿造安装libjpeg

重新安装枕头(我用枕头代替PIL)

点安装-我枕头

On Mac OS X Mavericks (10.9.3), I solved this by doing the follows:

Install libjpeg by brew (package management system)

brew install libjpeg

reinstall pillow (I use pillow instead of PIL)

pip install -I pillow


回答 7

apt-get install libjpeg-dev
apt-get install libfreetype6-dev
apt-get install zlib1g-dev
apt-get install libpng12-dev

安装这些文件并确保使用pip安装PIL,因为我是从源代码编译它的,由于某种原因它不起作用

apt-get install libjpeg-dev
apt-get install libfreetype6-dev
apt-get install zlib1g-dev
apt-get install libpng12-dev

Install these and be sure to install PIL with pip because I compiled it from source and for some reason it didn’t work


回答 8

我已经在使用Pillow并且遇到了同样的错误。尝试安装libjpeglibjpeg-dev按照其他人的建议进行安装,但被告知已经安装了(较新的)版本。

最后只需要重新安装Pillow

sudo pip uninstall Pillow
sudo pip install Pillow

I was already using Pillow and got the same error. Tried installing libjpeg or libjpeg-dev as suggested by others but was told that a (newer) version was already installed.

In the end all it took was reinstalling Pillow:

sudo pip uninstall Pillow
sudo pip install Pillow

回答 9

我太新手,无法评论zeantsoi post;(。因此,这里他需要做的工作才能在10.9.1上的OSX上解决

IOError:解码器jpeg不可用

1)安装Xcode工具(打开您的终端并执行: xcode-select --install)-摘自本文:Mac OS X 10.9之后无法安装PIL

2)从此链接安装libpng和libjpeg软件包(组合安装程序):http : //ethan.tira-thompson.com/Mac_OS_X_Ports.html

3)重新启动(不确定是否是强制性的)

4)使用run 重新安装PILpip install -I PIL(就像我在出现问题之前最初安装PIL一样)

希望有帮助,不要混淆更多…

_oho

I’m too newbie to comment zeantsoi post ;(. So here his what I needed to do to solved on OSX on 10.9.1 the

IOError: decoder jpeg not available

1) install Xcode tools (open your terminal and execute: xcode-select --install) – taken from this post: Can’t install PIL after Mac OS X 10.9

2) install libpng and libjpeg package (combo installer) from this link: http://ethan.tira-thompson.com/Mac_OS_X_Ports.html

3) reboot (not sure it was mandatory)

4) Re-install PIL with run pip install -I PIL (as I had initially installed PIL before having the issue)

Hope this help and don’t confuse more …

_oho


回答 10

这个问题是在很久以前发布的,而且大多数答案也很老。因此,当我花数小时试图弄清楚这一点时,没有任何效果,并且我尝试了本文中的所有建议。

尝试以Django头像形式上载JPG时,我仍然遇到标准JPEG错误:

raise IOError("decoder %s not available" % decoder_name)
OSError: decoder jpeg not available

然后,我检查了Ubuntu 12.04的存储库,发现有一些额外的软件包libjpeg。我安装了这些,问题就解决了:

sudo apt-get install libjpeg62 libjpeg62-dev

安装这些去掉libjpeg-devlibjpeg-turbo8-devlibjpeg8-dev

希望这对2015年及以后的人有所帮助!

干杯

This question was posted quite a while ago and most of the answers are quite old too. So when I spent hours trying to figure this out, nothing worked, and I tried all suggestions in this post.

I was still getting the standard JPEG errors when trying to upload a JPG in my Django avatar form:

raise IOError("decoder %s not available" % decoder_name)
OSError: decoder jpeg not available

Then I checked the repository for Ubuntu 12.04 and noticed some extra packages for libjpeg. I installed these and my problem was solved:

sudo apt-get install libjpeg62 libjpeg62-dev

Installing these removed libjpeg-dev, libjpeg-turbo8-dev, and libjpeg8-dev.

Hope this helps someone in the year 2015 and beyond!

Cheers


回答 11

同样的问题在这里,JPEG support available但是仍然得到了IOError: decoder/encoder jpeg not available,除了我使用枕头而不是PIL。

我尝试了以上所有方法,但经过多个小时,我意识到与结合使用sudo pip install不能按预期工作virtualenv。傻我

使用sudo有效在未激活virtualenv 的新外壳中启动命令(我的理解可能并不完全正确),这意味着这些软件包将安装在全局环境中。(这把事情弄糟了,我想我有2个不同的Pillow安装。)

我清理了所有内容,将用户更改为root,然后将其重新安装在virtualenv中,现在可以使用了。
希望这会帮助某人!

Same problem here, JPEG support available but still got IOError: decoder/encoder jpeg not available, except I use Pillow and not PIL.

I tried all of the above and more, but after many hours I realized that using sudo pip install does not work as I expected, in combination with virtualenv. Silly me.

Using sudo effectively launches the command in a new shell (my understanding of this may not be entirely correct) where the virtualenv is not activated, meaning that the packages will be installed in the global environment instead. (This messed things up, I think I had 2 different installations of Pillow.)

I cleaned things up, changed user to root and reinstalled in the virtualenv and now it works.
Hopefully this will help someone!


回答 12

对于Fedora

安装必备组件
sudo dnf install make automake gcc gcc-c++ kernel-devel rpm-build libjpeg-devel zlib-devel python-devel
现在安装枕头

sudo pip install pillow

注意-对于libjpeg和zlib,我们在Fedora / CentOS / Red Hat 中安装libjpeg-develzlib-devel软件包。

For Fedora

Install pre-requisite
sudo dnf install make automake gcc gcc-c++ kernel-devel rpm-build libjpeg-devel zlib-devel python-devel
Now install Pillow

sudo pip install pillow

Note – For libjpeg and zlib we are installing libjpeg-devel and zlib-devel packages in Fedora/CentOS/Red Hat


回答 13

首先,除了卸载Python之外,我还必须删除隐藏文件夹user / appData中的python文件夹(这很麻烦)。然后,我安装了WinPython发行版:http : //code.google.com/p/winpython/,其中包含PIL

First I had to delete the python folders in hidden folder user/appData (that was creating huge headaches), in addition to uninstalling Python. Then I installed WinPython Distribution: http://code.google.com/p/winpython/ which includes PIL


回答 14

对于Mac OS Mountain Lion上的用户,我遵循了zeantsoi的提示,但是它不起作用。

我最终以这篇文章的解决方案结束:http : //appelfreelance.com/2010/06/libjpeg-pil-snow-leopard-python2-6-__jpeg_resync_to_restart/

现在,我很高兴为jpeg运行脚本!

For those on Mac OS Mountain Lion, I followed the anwser of zeantsoi, but it doesn’t work.

I finally ended up with the solution of this post: http://appelfreelance.com/2010/06/libjpeg-pil-snow-leopard-python2-6-_jpeg_resync_to_restart/

Now, I’m happily running my script for jpeg !


Python的eval()有什么作用?

问题:Python的eval()有什么作用?

在我用Python阅读的书中,它一直在使用代码 eval(input('blah'))

我阅读了文档,但我理解了它,但仍然看不到它如何更改input()功能。

它有什么作用?有人可以解释吗?

In the book that I am reading on Python, it keeps using the code eval(input('blah'))

I read the documentation, and I understand it, but I still do not see how it changes the input() function.

What does it do? Can someone explain?


回答 0

eval函数允许Python程序在其内部运行Python代码。

评估示例(交互式外壳):

>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1

The eval function lets a Python program run Python code within itself.

eval example (interactive shell):

>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1

回答 1

eval()将字符串解释为代码。之所以有如此多的人警告您使用此功能,是因为用户可以将其用作在计算机上运行代码的选项。如果你有eval(input())os进口的,一个人可以键入input() os.system('rm -R *')这将删除你的家目录中的所有文件。(假设您有一个Unix系统)。使用eval()是一个安全漏洞。如果您需要将字符串转换为其他格式,请尝试使用可实现此目的的东西int()

eval() interprets a string as code. The reason why so many people have warned you about using this is because a user can use this as an option to run code on the computer. If you have eval(input()) and os imported, a person could type into input() os.system('rm -R *') which would delete all your files in your home directory. (Assuming you have a unix system). Using eval() is a security hole. If you need to convert strings to other formats, try to use things that do that, like int().


回答 2

这里有很多很好的答案,但没有一个描述在eval()globalslocalskwargs 的上下文中的使用,即eval(expression, globals=None, locals=None)(请参阅此处的文档eval )。

这些可用于限制可通过eval功能使用的功能。例如,如果您加载了一个新的python解释器,则locals()globals()将是相同的,看起来像这样:

>>>globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
 '__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
 '__package__': None, '__name__': '__main__'}

builtins模块中肯定有一些功能可能会对系统造成重大损害。但是可以阻止任何我们不希望使用的东西。让我们举个例子。假设我们要构建一个列表,以表示系统上可用内核的域。对我来说,我有8个核心,因此我需要一个清单[1, 8]

>>>from os import cpu_count
>>>eval('[1, cpu_count()]')
[1, 8]

同样,所有这些__builtins__都可用。

>>>eval('abs(-1)')
1

好。因此,我们看到了一个我们想要公开的函数,以及一个我们不想公开的方法(其中许多可能更为复杂)的示例。因此,让我们阻止一切。

>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable

我们有效地阻止了所有__builtins__功能,因此为我们的系统带来了一定程度的保护。在这一点上,我们可以开始添加我们想要公开的功能。

>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable

现在,我们可以使用该cpu_count功能,同时仍可以阻止所有不需要的功能。在我看来,这是非常强大的,并且显然是在其他答案的范围内,而不是常见的实现。诸如此类的东西有很多用途,只要处理得当,我个人认为eval可以安全地使用它,并获得很高的价值。

NB

这些方面很酷的一点kwargs是,您可以开始为代码使用简写形式。假设您将eval用作执行某些导入文本的管道的一部分。文本不需要确切的代码,它可以遵循某些模板文件格式,并且仍然可以执行所需的任何操作。例如:

>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]

Lots of good answers here, but none describe the use of eval() in the context of its globals and locals kwargs, i.e. eval(expression, globals=None, locals=None) (see docs for eval here).

These can be used to limit the functions that are available through the eval function. For example if you load up a fresh python interpreter the locals() and globals() will be the same and look something like this:

>>>globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
 '__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
 '__package__': None, '__name__': '__main__'}

There are certainly functions within the builtins module that can do significant damage to a system. But it is possible to block anything and everything we don’t want available. Let’s take an example. Say we want to construct a list to represent a domain of the available cores on a system. For me I have 8 cores so I would want a list [1, 8].

>>>from os import cpu_count
>>>eval('[1, cpu_count()]')
[1, 8]

Likewise all of __builtins__ is available.

>>>eval('abs(-1)')
1

Ok. So there we see one function we want exposed and an example of one (of many that can be much more complex) method that we do not want exposed. So let’s block everything.

>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable

We have effectively blocked all of the __builtins__ functions and as such brought a level of protection into our system. At this point we can start to add back in functions that we do want exposed.

>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable

Now we have the cpu_count function available while still blocking everything we do not want. In my opinion, this is super powerful and clearly from the scope of the other answers, not a common implementation. There are numerous uses for something like this and as long as it is handled correctly I personally feel eval can be safely used to great value.

N.B.

Something else that is cool about these kwargs is that you can start to use shorthand for your code. Let’s say you use eval as part of a pipeline to execute some imported text. The text doesn’t need to have exact code, it can follow some template file format, and still execute anything you’d like. For example:

>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]

回答 3

在Python 2.x input(...)中等效于eval(raw_input(...)),在Python 3.x中raw_input已重命名input,我怀疑这会引起您的困惑(您可能正在查看inputPython 2.x 的文档)。此外,eval(input(...))在Python 3.x中可以正常工作,但TypeError在Python 2中可以提高a 。

在这种情况下eval,用于强制将返回的字符串input转换为表达式并进行解释。通常,这被认为是不良做法。

In Python 2.x input(...) is equivalent to eval(raw_input(...)), in Python 3.x raw_input was renamed input, which I suspect lead to your confusion (you were probably looking at the documentation for input in Python 2.x). Additionally, eval(input(...)) would work fine in Python 3.x, but would raise a TypeError in Python 2.

In this case eval is used to coerce the string returned from input into an expression and interpreted. Generally this is considered bad practice.


回答 4

也许是读一行并解释它的一个令人误解的例子。

尝试eval(input())输入"1+1"-这应该打印出来2。Eval计算表达式。

Maybe a misleading example of reading a line and interpreting it.

Try eval(input()) and type "1+1" – this should print 2. Eval evaluates expressions.


回答 5

eval()将传递的字符串评估为Python表达式并返回结果。例如,eval("1 + 1")解释并执行表达式"1 + 1"并返回结果(2)。

您可能会感到困惑的一个原因是,您引用的代码涉及一种间接级别。内部函数调用(输入)首先执行,因此用户看到“ blah”提示。假设它们以“ 1 +1”响应(为清楚起见添加了引号,请在运行程序时不要键入它们),输入函数返回该字符串,然后将其传递给外部函数(eval),该函数解释该字符串并返回结果(2)。

在此处阅读有关eval的更多信息。

eval() evaluates the passed string as a Python expression and returns the result. For example, eval("1 + 1") interprets and executes the expression "1 + 1" and returns the result (2).

One reason you might be confused is because the code you cited involves a level of indirection. The inner function call (input) gets executed first so the user sees the “blah” prompt. Let’s imagine they respond with “1 + 1” (quotes added for clarity, don’t type them when running your program), the input function returns that string, which is then passed to the outer function (eval) which interprets the string and returns the result (2).

Read more about eval here.


回答 6

eval()顾名思义,它评估传递的参数。

raw_input()现在input()是python 3.x版本。因此,最常见的使用示例eval()是它用于提供input()python 2.x版本提供的功能。raw_input以字符串的形式返回用户输入的数据,而input评估输入的数据的值并返回它。

eval(input("bla bla"))因此复制了input()2.x中的功能,即评估用户输入的数据。

简而言之:eval()计算传递给它的参数并因此eval('1 + 1')返回2。

eval(), as the name suggests, evaluates the passed argument.

raw_input() is now input() in python 3.x versions. So the most commonly found example for the use of eval() is its use to provide the functionality that input() provided in 2.x version of python. raw_input returned the user-entered data as a string, while input evaluated the value of data entered and returned it.

eval(input("bla bla")) thus replicates the functionality of input() in 2.x, i.e., of evaluating the user-entered data.

In short: eval() evaluates the arguments passed to it and hence eval('1 + 1') returned 2.


回答 7

的有用应用之一eval()是从字符串评估python表达式。例如从字典的文件字符串表示形式加载:

running_params = {"Greeting":"Hello "}
fout = open("params.dat",'w')
fout.write(repr(running_params))
fout.close()

将其作为变量读取并编辑:

fin = open("params.dat",'r')
diction=eval(fin.read())
diction["Greeting"]+="world"
fin.close()
print diction

输出:

{'Greeting': 'Hello world'}

One of useful applications of eval() is to evaluate python expressions from string. For example load from file string representation of dictionary:

running_params = {"Greeting":"Hello "}
fout = open("params.dat",'w')
fout.write(repr(running_params))
fout.close()

Read it out as a variable and edit it:

fin = open("params.dat",'r')
diction=eval(fin.read())
diction["Greeting"]+="world"
fin.close()
print diction

Output:

{'Greeting': 'Hello world'}

回答 8

我迟迟未回答这个问题,但是似乎没人能给出明确的答案。

如果用户输入数字值,input()将返回一个字符串。

>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'

因此,eval()将评估作为字符串的返回值(或表达式),并返回整数/浮点数。

>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>> 
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14

当然,这是一个坏习惯。int()或在这种情况下float()应使用eval()

>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14

I’m late to answer this question but, no one seems to give clear answer to the question.

If an user enters a numeric value, input() will return a string.

>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'

So, eval() will evaluate returned value (or expression) which is a string and return integer/float.

>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>> 
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14

Of cource this is a bad practice. int() or float() should be used instead of eval() in this case.

>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14

回答 9

如果要将评估字符串限制为简单文字,则可以使用ast.literal_eval()。一些例子:

import ast

# print(ast.literal_eval(''))          # SyntaxError: unexpected EOF while parsing
# print(ast.literal_eval('a'))         # ValueError: malformed node or string
# print(ast.literal_eval('import os')) # SyntaxError: invalid syntax
# print(ast.literal_eval('1+1'))       # 2: but only works due to a quirk in parser
# print(ast.literal_eval('1*1'))       # ValueError: malformed node or string
print(ast.literal_eval("{'a':1}"))     # {'a':1}

文档

安全地评估表达式节点或包含Python文字或容器显示的字符串。提供的字符串或节点只能由以下Python文字结构组成:字符串,字节,数字,元组,列表,字典,集合,布尔值和无。

这可用于安全地评估包含来自不受信任来源的Python值的字符串,而无需自己解析值。它不能评估任意复杂的表达式,例如涉及运算符或索引的表达式。

至于为什么如此有限,请从邮件列表中进行

允许带有文字的运算符表达式是可能的,但是比当前实现复杂得多。一个简单的实现并不安全:您可以毫不费力地诱导CPU和内存的使用不受限制(尝试“ 9 ** 9 ** 9”或“ [无] * 9 ** 9”)。

至于有用性,此函数对于“读回”由repr()字符串化的文字值和容器很有用。例如,它可以用于序列化,其格式类似于JSON,但功能比JSON更强大。

Another option if you want to limit the evaluation string to simple literals is to use ast.literal_eval(). Some examples:

import ast

# print(ast.literal_eval(''))          # SyntaxError: unexpected EOF while parsing
# print(ast.literal_eval('a'))         # ValueError: malformed node or string
# print(ast.literal_eval('import os')) # SyntaxError: invalid syntax
# print(ast.literal_eval('1+1'))       # 2: but only works due to a quirk in parser
# print(ast.literal_eval('1*1'))       # ValueError: malformed node or string
print(ast.literal_eval("{'a':1}"))     # {'a':1}

From the docs:

Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.

This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.

As for why it’s so limited, from the mailing list:

Allowing operator expressions with literals is possible, but much more complex than the current implementation. A simple implementation is not safe: you can induce basically unbounded CPU and memory usage with no effort (try “9**9**9” or “[None] * 9**9”).

As for the usefulness, this function is useful to “read back” literal values and containers as stringified by repr(). This can for example be used for serialization in a format that is similar to but more powerful than JSON.


为什么范围(开始,结束)不包括结束?

问题:为什么范围(开始,结束)不包括结束?

>>> range(1,11)

给你

[1,2,3,4,5,6,7,8,9,10]

为什么不选择1-11?

他们是只是决定随机地这样做,还是有一些我没有看到的价值?

>>> range(1,11)

gives you

[1,2,3,4,5,6,7,8,9,10]

Why not 1-11?

Did they just decide to do it like that at random or does it have some value I am not seeing?


回答 0

因为调用range(0, 10)return [0,1,2,3,4,5,6,7,8,9]包含10个等于equals的元素更为常见len(range(0, 10))。请记住,程序员更喜欢基于0的索引。

另外,请考虑以下常见代码段:

for i in range(len(li)):
    pass

您能看到如果range()精确len(li)到这将是有问题的吗?程序员需要显式减1。这也遵循程序员喜欢的共同趋势for(int i = 0; i < 10; i++)for(int i = 0; i <= 9; i++)

如果您经常以1开头的范围调用range,则可能需要定义自己的函数:

>>> def range1(start, end):
...     return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Because it’s more common to call range(0, 10) which returns [0,1,2,3,4,5,6,7,8,9] which contains 10 elements which equals len(range(0, 10)). Remember that programmers prefer 0-based indexing.

Also, consider the following common code snippet:

for i in range(len(li)):
    pass

Could you see that if range() went up to exactly len(li) that this would be problematic? The programmer would need to explicitly subtract 1. This also follows the common trend of programmers preferring for(int i = 0; i < 10; i++) over for(int i = 0; i <= 9; i++).

If you are calling range with a start of 1 frequently, you might want to define your own function:

>>> def range1(start, end):
...     return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

回答 1

尽管这里有一些有用的算法解释,但我认为添加一些简单的“现实生活”推理可能会有助于以这种方式工作,这对我向年轻新手介绍该主题很有用:

对于“ range(1,10)”之类的东西,可能会因认为一对参数代表“开始和结束”而产生混淆。

它实际上是开始和“停止”。

现在,如果它 “结束”值,是的,您可能希望该数字将作为序列中的最后一个条目包括在内。但这不是“终点”。

其他人错误地将该参数称为“ count”,因为如果您只使用“ range(n)”,那么它当然会迭代“ n”次。添加开始参数时,此逻辑将失效。

因此,关键是要记住它的名称:“ stop ”。这意味着到达该点时,迭代将立即停止。不经过这一点。

因此,虽然“开始”确实代表要包含的第一个值,但在达到“停止”值时,它“中断”而不是在停止之前继续处理“该一个”。

我用来向孩子们解释的一个比喻是,具有讽刺意味的是,它比孩子们表现得更好!它不会应有的状态下停止-它会在未完成操作的情况下立即停止。(他们得到这个;)

另一个比喻-当您开车时,您不会通过停车/屈服/“放弃”标志,而最终会停在您的汽车旁边或后面。从技术上讲,您停止时仍未达到目标。它不包含在“您在旅途中传递的事物”中。

我希望其中一些有助于解释Pythonitos / Pythonitas!

Although there are some useful algorithmic explanations here, I think it may help to add some simple ‘real life’ reasoning as to why it works this way, which I have found useful when introducing the subject to young newcomers:

With something like ‘range(1,10)’ confusion can arise from thinking that pair of parameters represents the “start and end”.

It is actually start and “stop”.

Now, if it were the “end” value then, yes, you might expect that number would be included as the final entry in the sequence. But it is not the “end”.

Others mistakenly call that parameter “count” because if you only ever use ‘range(n)’ then it does, of course, iterate ‘n’ times. This logic breaks down when you add the start parameter.

So the key point is to remember its name: “stop“. That means it is the point at which, when reached, iteration will stop immediately. Not after that point.

So, while “start” does indeed represent the first value to be included, on reaching the “stop” value it ‘breaks’ rather than continuing to process ‘that one as well’ before stopping.

One analogy that I have used in explaining this to kids is that, ironically, it is better behaved than kids! It doesn’t stop after it supposed to – it stops immediately without finishing what it was doing. (They get this ;) )

Another analogy – when you drive a car you don’t pass a stop/yield/’give way’ sign and end up with it sitting somewhere next to, or behind, your car. Technically you still haven’t reached it when you do stop. It is not included in the ‘things you passed on your journey’.

I hope some of that helps in explaining to Pythonitos/Pythonitas!


回答 2

互斥范围确实有一些好处:

一方面,每一项range(0,n)都是长度列表的有效索引n

range(0,n)具有的长度n,不是n+1包含范围的长度。

Exclusive ranges do have some benefits:

For one thing each item in range(0,n) is a valid index for lists of length n.

Also range(0,n) has a length of n, not n+1 which an inclusive range would.


回答 3

与基于零的索引和结合使用时效果很好len()。例如,如果列表中有10个项目x,则它们的编号为0-9。range(len(x))给你0-9。

当然,人们会告诉你这是更Python做for item in xfor index, item in enumerate(x)不是for i in range(len(x))

切片也是如此:foo[1:4]是项的1-3 foo(请记住,由于从零开始的索引,项1实际上是第二项)。为了保持一致,它们都应以相同的方式工作。

我认为它是:“您想要的第一个数字,然后是您不需要的第一个数字。” 如果您想要1-10,则您不希望的第一个数字是11,所以它是range(1, 11)

如果它在特定的应用程序中变得繁琐,那么编写一个简单的辅助函数就很容易了,该函数将1加到结束索引并调用range()

It works well in combination with zero-based indexing and len(). For example, if you have 10 items in a list x, they are numbered 0-9. range(len(x)) gives you 0-9.

Of course, people will tell you it’s more Pythonic to do for item in x or for index, item in enumerate(x) rather than for i in range(len(x)).

Slicing works that way too: foo[1:4] is items 1-3 of foo (keeping in mind that item 1 is actually the second item due to the zero-based indexing). For consistency, they should both work the same way.

I think of it as: “the first number you want, followed by the first number you don’t want.” If you want 1-10, the first number you don’t want is 11, so it’s range(1, 11).

If it becomes cumbersome in a particular application, it’s easy enough to write a little helper function that adds 1 to the ending index and calls range().


回答 4

这对于分割范围也很有用;range(a,b)可以分为range(a, x)range(x, b),而在包含范围内,您可以编写x-1x+1。尽管您几乎不需要拆分范围,但您确实倾向于拆分列表,这是对列表进行切片的原因之一,其中l[a:b]包括第a个元素,但不包括第b个元素。然后range具有相同的属性使其完全一致。

It’s also useful for splitting ranges; range(a,b) can be split into range(a, x) and range(x, b), whereas with inclusive range you would write either x-1 or x+1. While you rarely need to split ranges, you do tend to split lists quite often, which is one of the reasons slicing a list l[a:b] includes the a-th element but not the b-th. Then range having the same property makes it nicely consistent.


回答 5

范围的长度是上限值减去下限值。

它非常类似于以下内容:

for (var i = 1; i < 11; i++) {
    //i goes from 1 to 10 in here
}

用C风格的语言。

也像Ruby的范围:

1...11 #this is a range from 1 to 10

但是,Ruby认识到很多时候您都想包含终端值,并提供了另一种语法:

1..10 #this is also a range from 1 to 10

The length of the range is the top value minus the bottom value.

It’s very similar to something like:

for (var i = 1; i < 11; i++) {
    //i goes from 1 to 10 in here
}

in a C-style language.

Also like Ruby’s range:

1...11 #this is a range from 1 to 10

However, Ruby recognises that many times you’ll want to include the terminal value and offers the alternative syntax:

1..10 #this is also a range from 1 to 10

回答 6

基本上在python中range(n)迭代n时间,这是排他性,这就是为什么它在打印时不给出最后一个值的原因,我们可以创建一个给出包容性值的函数,这意味着它也将打印范围中提到的最后一个值。

def main():
    for i in inclusive_range(25):
        print(i, sep=" ")


def inclusive_range(*args):
    numargs = len(args)
    if numargs == 0:
        raise TypeError("you need to write at least a value")
    elif numargs == 1:
        stop = args[0]
        start = 0
        step = 1
    elif numargs == 2:
        (start, stop) = args
        step = 1
    elif numargs == 3:
        (start, stop, step) = args
    else:
        raise TypeError("Inclusive range was expected at most 3 arguments,got {}".format(numargs))
    i = start
    while i <= stop:
        yield i
        i += step


if __name__ == "__main__":
    main()

Basically in python range(n) iterates n times, which is of exclusive nature that is why it does not give last value when it is being printed, we can create a function which gives inclusive value it means it will also print last value mentioned in range.

def main():
    for i in inclusive_range(25):
        print(i, sep=" ")


def inclusive_range(*args):
    numargs = len(args)
    if numargs == 0:
        raise TypeError("you need to write at least a value")
    elif numargs == 1:
        stop = args[0]
        start = 0
        step = 1
    elif numargs == 2:
        (start, stop) = args
        step = 1
    elif numargs == 3:
        (start, stop, step) = args
    else:
        raise TypeError("Inclusive range was expected at most 3 arguments,got {}".format(numargs))
    i = start
    while i <= stop:
        yield i
        i += step


if __name__ == "__main__":
    main()

回答 7

考虑代码

for i in range(10):
    print "You'll see this 10 times", i

想法是获得一个length的列表y-x,您可以(如上所述)进行迭代。

阅读有关范围的python文档 -他们将for循环迭代视为主要用例。

Consider the code

for i in range(10):
    print "You'll see this 10 times", i

The idea is that you get a list of length y-x, which you can (as you see above) iterate over.

Read up on the python docs for range – they consider for-loop iteration the primary usecase.


回答 8

在许多情况下,这样做更方便。

基本上,我们可以将范围视为start和之间的间隔end。如果是start <= end,则它们之间的间隔长度为end - start。如果len实际定义为长度,则将具有:

len(range(start, end)) == start - end

但是,我们计算范围内包含的整数,而不是测量间隔的长度。为了保持上述属性为真,我们应包括一个端点,而排除另一个端点。

添加step参数就像引入长度单位一样。在这种情况下,您会期望

len(range(start, end, step)) == (start - end) / step

对于长度。要获得计数,您只需使用整数除法。

It’s just more convenient to reason about in many cases.

Basically, we could think of a range as an interval between start and end. If start <= end, the length of the interval between them is end - start. If len was actually defined as the length, you’d have:

len(range(start, end)) == start - end

However, we count the integers included in the range instead of measuring the length of the interval. To keep the above property true, we should include one of the endpoints and exclude the other.

Adding the step parameter is like introducing a unit of length. In that case, you’d expect

len(range(start, end, step)) == (start - end) / step

for length. To get the count, you just use integer division.