标签归档:Python

如何导入其他Python文件?

问题:如何导入其他Python文件?

如何在Python中导入其他文件?

  1. 我到底该如何导入特定的python文件import file.py呢?
  2. 如何导入文件夹而不是特定文件?
  3. 我想根据用户输入在运行时动态加载Python文件。
  4. 我想知道如何从文件中仅加载一个特定部分。

例如,在main.py我有:

from extra import * 

尽管这给了我中的所有定义extra.py,但也许我只想要一个定义:

def gap():
    print
    print

我要从import语句中添加什么?gapextra.py

How do I import other files in Python?

  1. How exactly can I import a specific python file like import file.py?
  2. How can I import a folder instead of a specific file?
  3. I want to load a Python file dynamically at runtime, based on user input.
  4. I want to know how to load just one specific part from the file.

For example, in main.py I have:

from extra import * 

Although this gives me all the definitions in extra.py, when maybe all I want is a single definition:

def gap():
    print
    print

What do I add to the import statement to just get gap from extra.py?


回答 0

importlib已添加到Python 3中,以编程方式导入模块。它只是一个包装__import__,请参阅文档

import importlib

moduleName = input('Enter module name:')
importlib.import_module(moduleName)

注意:.py扩展名应从中删除moduleName。该函数还package为相对导入定义了一个参数。


更新:以下答案已过时。使用上面的最新替代方法。

  1. 只是import file没有’.py’扩展名。

  2. 您可以通过添加一个名为的空文件来将文件夹标记为包__init__.py

  3. 您可以使用该__import__功能。它以模块名称作为字符串。(同样:模块名称不带“ .py”扩展名。)

    pmName = input('Enter module name:')
    pm = __import__(pmName)
    print(dir(pm))
    

    输入help(__import__)以获取更多详细信息。

importlib was added to Python 3 to programmatically import a module. It is just a wrapper around __import__, see the docs.

import importlib

moduleName = input('Enter module name:')
importlib.import_module(moduleName)

Note: the .py extension should be removed from moduleName. The function also defines a package argument for relative imports.


Update: Answer below is outdated. Use the more recent alternative above.

  1. Just import file without the ‘.py’ extension.

  2. You can mark a folder as a package, by adding an empty file named __init__.py.

  3. You can use the __import__ function. It takes the module name as a string. (Again: module name without the ‘.py’ extension.)

    pmName = input('Enter module name:')
    pm = __import__(pmName)
    print(dir(pm))
    

    Type help(__import__) for more details.


回答 1

导入python文件的方法有很多,各有利弊。

不要只是匆忙地选择适合您的第一个导入策略,否则您将不得不在以后发现无法满足您的需要时重写代码库。

我将首先说明最简单的示例#1,然后将介绍最专业,最可靠的示例#7

示例1,使用python解释器导入python模块:

  1. 将其放在/home/el/foo/fox.py中:

    def what_does_the_fox_say():
      print("vixens cry")
  2. 进入python解释器:

    el@apollo:/home/el/foo$ python
    Python 2.7.3 (default, Sep 26 2013, 20:03:06) 
    >>> import fox
    >>> fox.what_does_the_fox_say()
    vixens cry
    >>> 

    您通过python解释器导入了fox,并what_does_the_fox_say()从fox.py中调用了python函数。

示例2,在脚本中使用execfile或(exec在Python 3中)在适当的位置执行另一个python文件:

  1. 将其放在/home/el/foo2/mylib.py中:

    def moobar():
      print("hi")
  2. 将其放在/home/el/foo2/main.py中:

    execfile("/home/el/foo2/mylib.py")
    moobar()
  3. 运行文件:

    el@apollo:/home/el/foo$ python main.py
    hi

    功能moobar是从mylib.py导入的,并在main.py中可用

示例3,从…使用…导入…功能:

  1. 将其放在/home/el/foo3/chekov.py中:

    def question():
      print "where are the nuclear wessels?"
  2. 将其放在/home/el/foo3/main.py中:

    from chekov import question
    question()
  3. 像这样运行它:

    el@apollo:/home/el/foo3$ python main.py 
    where are the nuclear wessels?

    如果您在chekov.py中定义了其他函数,除非您定义了这些函数,否则它们将不可用。 import *

示例4,如果导入的riaa.py与导入的文件位于不同的文件位置

  1. 将其放在/home/el/foo4/stuff/riaa.py中:

    def watchout():
      print "computers are transforming into a noose and a yoke for humans"
  2. 将其放在/home/el/foo4/main.py中:

    import sys 
    import os
    sys.path.append(os.path.abspath("/home/el/foo4/stuff"))
    from riaa import *
    watchout()
  3. 运行:

    el@apollo:/home/el/foo4$ python main.py 
    computers are transforming into a noose and a yoke for humans

    那会从另一个目录导入外部文件中的所有内容。

示例5,使用 os.system("python yourfile.py")

import os
os.system("python yourfile.py")

示例6,通过piggy带python startuphook导入文件:

更新:此示例曾经同时适用于python2和3,但现在仅适用于python2。python3摆脱了此用户启动钩子功能集,因为它被低技能的python库编写者滥用,使用它在所有用户定义的程序之前不礼貌地将其代码注入到全局命名空间中。如果您希望此功能适用于python3,则必须变得更有创意。如果我告诉您如何做,python开发人员也会禁用该功能集,因此您是一个人。

参见:https : //docs.python.org/2/library/user.html

将此代码放入您的主目录中 ~/.pythonrc.py

class secretclass:
    def secretmessage(cls, myarg):
        return myarg + " is if.. up in the sky, the sky"
    secretmessage = classmethod( secretmessage )

    def skycake(cls):
        return "cookie and sky pie people can't go up and "
    skycake = classmethod( skycake )

将此代码放入您的main.py(可以在任何地方):

import user
msg = "The only way skycake tates good" 
msg = user.secretclass.secretmessage(msg)
msg += user.secretclass.skycake()
print(msg + " have the sky pie! SKYCAKE!")

运行它,您应该获得以下信息:

$ python main.py
The only way skycake tates good is if.. up in the sky, 
the skycookie and sky pie people can't go up and  have the sky pie! 
SKYCAKE!

如果您在这里遇到错误:ModuleNotFoundError: No module named 'user'这意味着您正在使用python3,默认情况下会禁用启动钩。

值得一提的是:https : //github.com/docwhat/homedir-examples/blob/master/python-commandline/.pythonrc.py随便 发送。

示例7,最健壮:使用裸导入命令在python中导入文件:

  1. 建立一个新目录 /home/el/foo5/
  2. 建立一个新目录 /home/el/foo5/herp
  3. 制作一个以__init__.pyherp 命名的空文件:

    el@apollo:/home/el/foo5/herp$ touch __init__.py
    el@apollo:/home/el/foo5/herp$ ls
    __init__.py
  4. 新建一个目录/ home / el / foo5 / herp / derp

  5. 在derp下,制作另一个__init__.py文件:

    el@apollo:/home/el/foo5/herp/derp$ touch __init__.py
    el@apollo:/home/el/foo5/herp/derp$ ls
    __init__.py
  6. 在/ home / el / foo5 / herp / derp下,创建一个名为yolo.pyPut this 的新文件:

    def skycake():
      print "SkyCake evolves to stay just beyond the cognitive reach of " +
      "the bulk of men. SKYCAKE!!"
  7. 关键时刻,创建新文件/home/el/foo5/main.py,并将其放入其中;

    from herp.derp.yolo import skycake
    skycake()
  8. 运行:

    el@apollo:/home/el/foo5$ python main.py
    SkyCake evolves to stay just beyond the cognitive reach of the bulk 
    of men. SKYCAKE!!

    __init__.py文件会通知python解释器开发人员打算将此目录作为可导入包。

如果您想查看我的帖子,如何在目录下包含所有.py文件,请参见此处:https : //stackoverflow.com/a/20753073/445131

There are many ways to import a python file, all with their pros and cons.

Don’t just hastily pick the first import strategy that works for you or else you’ll have to rewrite the codebase later on when you find it doesn’t meet your needs.

I’ll start out explaining the easiest example #1, then I’ll move toward the most professional and robust example #7

Example 1, Import a python module with python interpreter:

  1. Put this in /home/el/foo/fox.py:

    def what_does_the_fox_say():
      print("vixens cry")
    
  2. Get into the python interpreter:

    el@apollo:/home/el/foo$ python
    Python 2.7.3 (default, Sep 26 2013, 20:03:06) 
    >>> import fox
    >>> fox.what_does_the_fox_say()
    vixens cry
    >>> 
    

    You imported fox through the python interpreter, invoked the python function what_does_the_fox_say() from within fox.py.

Example 2, Use execfile or (exec in Python 3) in a script to execute the other python file in place:

  1. Put this in /home/el/foo2/mylib.py:

    def moobar():
      print("hi")
    
  2. Put this in /home/el/foo2/main.py:

    execfile("/home/el/foo2/mylib.py")
    moobar()
    
  3. run the file:

    el@apollo:/home/el/foo$ python main.py
    hi
    

    The function moobar was imported from mylib.py and made available in main.py

Example 3, Use from … import … functionality:

  1. Put this in /home/el/foo3/chekov.py:

    def question():
      print "where are the nuclear wessels?"
    
  2. Put this in /home/el/foo3/main.py:

    from chekov import question
    question()
    
  3. Run it like this:

    el@apollo:/home/el/foo3$ python main.py 
    where are the nuclear wessels?
    

    If you defined other functions in chekov.py, they would not be available unless you import *

Example 4, Import riaa.py if it’s in a different file location from where it is imported

  1. Put this in /home/el/foo4/stuff/riaa.py:

    def watchout():
      print "computers are transforming into a noose and a yoke for humans"
    
  2. Put this in /home/el/foo4/main.py:

    import sys 
    import os
    sys.path.append(os.path.abspath("/home/el/foo4/stuff"))
    from riaa import *
    watchout()
    
  3. Run it:

    el@apollo:/home/el/foo4$ python main.py 
    computers are transforming into a noose and a yoke for humans
    

    That imports everything in the foreign file from a different directory.

Example 5, use os.system("python yourfile.py")

import os
os.system("python yourfile.py")

Example 6, import your file via piggybacking the python startuphook:

Update: This example used to work for both python2 and 3, but now only works for python2. python3 got rid of this user startuphook feature set because it was abused by low-skill python library writers, using it to impolitely inject their code into the global namespace, before all user-defined programs. If you want this to work for python3, you’ll have to get more creative. If I tell you how to do it, python developers will disable that feature set as well, so you’re on your own.

See: https://docs.python.org/2/library/user.html

Put this code into your home directory in ~/.pythonrc.py

class secretclass:
    def secretmessage(cls, myarg):
        return myarg + " is if.. up in the sky, the sky"
    secretmessage = classmethod( secretmessage )

    def skycake(cls):
        return "cookie and sky pie people can't go up and "
    skycake = classmethod( skycake )

Put this code into your main.py (can be anywhere):

import user
msg = "The only way skycake tates good" 
msg = user.secretclass.secretmessage(msg)
msg += user.secretclass.skycake()
print(msg + " have the sky pie! SKYCAKE!")

Run it, you should get this:

$ python main.py
The only way skycake tates good is if.. up in the sky, 
the skycookie and sky pie people can't go up and  have the sky pie! 
SKYCAKE!

If you get an error here: ModuleNotFoundError: No module named 'user' then it means you’re using python3, startuphooks are disabled there by default.

Credit for this jist goes to: https://github.com/docwhat/homedir-examples/blob/master/python-commandline/.pythonrc.py Send along your up-boats.

Example 7, Most Robust: Import files in python with the bare import command:

  1. Make a new directory /home/el/foo5/
  2. Make a new directory /home/el/foo5/herp
  3. Make an empty file named __init__.py under herp:

    el@apollo:/home/el/foo5/herp$ touch __init__.py
    el@apollo:/home/el/foo5/herp$ ls
    __init__.py
    
  4. Make a new directory /home/el/foo5/herp/derp

  5. Under derp, make another __init__.py file:

    el@apollo:/home/el/foo5/herp/derp$ touch __init__.py
    el@apollo:/home/el/foo5/herp/derp$ ls
    __init__.py
    
  6. Under /home/el/foo5/herp/derp make a new file called yolo.py Put this in there:

    def skycake():
      print "SkyCake evolves to stay just beyond the cognitive reach of " +
      "the bulk of men. SKYCAKE!!"
    
  7. The moment of truth, Make the new file /home/el/foo5/main.py, put this in there;

    from herp.derp.yolo import skycake
    skycake()
    
  8. Run it:

    el@apollo:/home/el/foo5$ python main.py
    SkyCake evolves to stay just beyond the cognitive reach of the bulk 
    of men. SKYCAKE!!
    

    The empty __init__.py file communicates to the python interpreter that the developer intends this directory to be an importable package.

If you want to see my post on how to include ALL .py files under a directory see here: https://stackoverflow.com/a/20753073/445131


回答 2

要在“运行时”以已知名称导入特定的Python文件:

import os
import sys

scriptpath = "../Test/"

# Add the directory containing your module to the Python path (wants absolute paths)
sys.path.append(os.path.abspath(scriptpath))

# Do the import
import MyModule

To import a specific Python file at ‘runtime’ with a known name:

import os
import sys

scriptpath = "../Test/"

# Add the directory containing your module to the Python path (wants absolute paths)
sys.path.append(os.path.abspath(scriptpath))

# Do the import
import MyModule

回答 3

您没有很多复杂的方法可以将python文件从一个文件夹导入到另一个文件夹。只需创建一个__init__.py文件,以声明此文件夹为python软件包,然后转到要导入的主机文件即可,只需键入

from root.parent.folder.file import variable, class, whatever

You do not have many complex methods to import a python file from one folder to another. Just create a __init__.py file to declare this folder is a python package and then go to your host file where you want to import just type

from root.parent.folder.file import variable, class, whatever


回答 4

导入文档..-链接以供参考

__init__.py需要这些文件才能使Python将目录视为包含软件包的目录,这样做是为了防止具有通用名称(例如字符串)的目录无意间隐藏了稍后在模块搜索路径中出现的有效模块。

__init__.py可以只是一个空文件,但也可以执行包的初始化代码或设置__all__变量。

mydir/spam/__init__.py
mydir/spam/module.py
import spam.module
or
from spam import module

Import doc .. — Link for reference

The __init__.py files are required to make Python treat the directories as containing packages, this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path.

__init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable.

mydir/spam/__init__.py
mydir/spam/module.py
import spam.module
or
from spam import module

回答 5

第一种情况:您要在file A.py中导入文件B.py,这两个文件位于同一文件夹中,如下所示:

. 
├── A.py 
└── B.py

您可以在file中执行此操作B.py

import A

要么

from A import *

要么

from A import THINGS_YOU_WANT_TO_IMPORT_IN_A

然后,您将可以使用文件A.py中文件的所有功能B.py


第二种情况:您要在file folder/A.py中导入文件B.py,这两个文件不在同一文件夹中,如下所示:

.
├── B.py
└── folder
     └── A.py

您可以在文件B中执行此操作:

import folder.A

要么

from folder.A import *

要么

from folder.A import THINGS_YOU_WANT_TO_IMPORT_IN_A

然后,您将可以使用文件A.py中文件的所有功能B.py


摘要:在第一种情况下,file A.py是您在file中导入的模块,B.py使用了语法import module_name。在第二种情况下,使用的语法folder是包含模块的软件包。A.pyimport package_name.module_name

有关软件包和模块的更多信息,请参考此链接

First case: You want to import file A.py in file B.py, these two files are in the same folder, like this:

. 
├── A.py 
└── B.py

You can do this in file B.py:

import A

or

from A import *

or

from A import THINGS_YOU_WANT_TO_IMPORT_IN_A

Then you will be able to use all the functions of file A.py in file B.py


Second case: You want to import file folder/A.py in file B.py, these two files are not in the same folder, like this:

.
├── B.py
└── folder
     └── A.py

You can do this in file B:

import folder.A

or

from folder.A import *

or

from folder.A import THINGS_YOU_WANT_TO_IMPORT_IN_A

Then you will be able to use all the functions of file A.py in file B.py


Summary: In the first case, file A.py is a module that you imports in file B.py, you used the syntax import module_name. In the second case, folder is the package that contains the module A.py, you used the syntax import package_name.module_name.

For more info on packages and modules, consult this link.


回答 6

from file import function_name  ######## Importing specific function
function_name()                 ######## Calling function

import file              ######## Importing whole package
file.function1_name()    ######## Calling function
file.function2_name()    ######## Calling function

这是到目前为止我已经了解的两种简单方法,请确保要导入为库的“ file.py”文件仅存在于当前目录中。

from file import function_name  ######## Importing specific function
function_name()                 ######## Calling function

and

import file              ######## Importing whole package
file.function1_name()    ######## Calling function
file.function2_name()    ######## Calling function

Here are the two simple ways I have understood by now and make sure your “file.py” file which you want to import as a library is present in your current directory only.


回答 7

如果定义的函数在文件中x.py

def greet():
    print('Hello! How are you?')

在要导入函数的文件中,编写以下代码:

from x import greet

如果您不希望将所有功能导入文件中,这将很有用。

If the function defined is in a file x.py:

def greet():
    print('Hello! How are you?')

In the file where you are importing the function, write this:

from x import greet

This is useful if you do not wish to import all the functions in a file.


回答 8

导入.py文件的最佳方法是通过__init__.py。最简单的操作是__init__.py在your.py文件所在的目录中创建一个名为空文件。

Mike Grouchy的这篇文章很好地解释了__init__.py它在制作,导入和设置python包中的用途。

the best way to import .py files is by way of __init__.py. the simplest thing to do, is to create an empty file named __init__.py in the same directory that your.py file is located.

this post by Mike Grouchy is a great explanation of __init__.py and its use for making, importing, and setting up python packages.


回答 9

我的导入方式是导入文件并使用其名称的缩写。

import DoStuff.py as DS
DS.main()

不要忘记您的导入文件必须以.py扩展名命名

How I import is import the file and use shorthand of it’s name.

import DoStuff.py as DS
DS.main()

Don’t forget that your importing file MUST BE named with .py extension


回答 10

我想在其他地方加一个不太清楚的注释。在模块/软件包内部,从文件加载时,模块/软件包名称必须带有前缀mymodule。想象一下mymodule这样的布局:

/main.py
/mymodule
    /__init__.py
    /somefile.py
    /otherstuff.py

从内容中加载somefile.py/ 时应如下所示:otherstuff.py__init__.py

from mymodule.somefile import somefunc
from mymodule.otherstuff import otherfunc

I’d like to add this note I don’t very clearly elsewhere; inside a module/package, when loading from files, the module/package name must be prefixed with the mymodule. Imagine mymodule being layout like this:

/main.py
/mymodule
    /__init__.py
    /somefile.py
    /otherstuff.py

When loading somefile.py/otherstuff.py from __init__.py the contents should look like:

from mymodule.somefile import somefunc
from mymodule.otherstuff import otherfunc

回答 11

如果要导入的模块不在子目录中,请尝试以下操作并app.py从最深的公共父目录中运行:

目录结构:

/path/to/common_dir/module/file.py
/path/to/common_dir/application/app.py
/path/to/common_dir/application/subpath/config.json

在中app.py,将客户端路径附加到sys.path:

import os, sys, inspect

sys.path.append(os.getcwd())
from module.file import MyClass
instance = MyClass()

可选(如果您加载例如configs)(对于我的用例,检查似乎是最可靠的一种)

# Get dirname from inspect module
filename = inspect.getframeinfo(inspect.currentframe()).filename
dirname = os.path.dirname(os.path.abspath(filename))
MY_CONFIG = os.path.join(dirname, "subpath/config.json")

user@host:/path/to/common_dir$ python3 application/app.py

此解决方案在cli和PyCharm中都对我有效。

In case the module you want to import is not in a sub-directory, then try the following and run app.py from the deepest common parent directory:

Directory Structure:

/path/to/common_dir/module/file.py
/path/to/common_dir/application/app.py
/path/to/common_dir/application/subpath/config.json

In app.py, append path of client to sys.path:

import os, sys, inspect

sys.path.append(os.getcwd())
from module.file import MyClass
instance = MyClass()

Optional (If you load e.g. configs) (Inspect seems to be the most robust one for my use cases)

# Get dirname from inspect module
filename = inspect.getframeinfo(inspect.currentframe()).filename
dirname = os.path.dirname(os.path.abspath(filename))
MY_CONFIG = os.path.join(dirname, "subpath/config.json")

Run

user@host:/path/to/common_dir$ python3 application/app.py

This solution works for me in cli, as well as PyCharm.


回答 12

有几种方法可以包含名称为abc.py的python脚本

  1. 例如,如果您的文件名为abc.py(导入abc),则限制是文件应位于与您的调用python脚本相同的位置。

导入abc

  1. 例如,如果您的python文件位于Windows文件夹中。Windows文件夹位于您调用Python脚本的位置。

从文件夹导入abc

  1. 如果abc.py脚本在文件夹中存在的Insider Internal_folder内部可用

从folder.internal_folder导入abc

  1. 如上文James所述,如果您的文件位于某个固定位置

import os
import sys
scriptpath =“ ../Test/MyModule.py”
sys.path.append(os.path.abspath(scriptpath))
import MyModule

如果您的python脚本已更新并且不想上传,请使用这些语句进行自动刷新。奖金:)

%load_ext autoreload 
%autoreload 2

There are couple of ways of including your python script with name abc.py

  1. e.g. if your file is called abc.py (import abc) Limitation is that your file should be present in the same location where your calling python script is.

import abc

  1. e.g. if your python file is inside the Windows folder. Windows folder is present at the same location where your calling python script is.

from folder import abc

  1. Incase abc.py script is available insider internal_folder which is present inside folder

from folder.internal_folder import abc

  1. As answered by James above, in case your file is at some fixed location

import os
import sys
scriptpath = “../Test/MyModule.py”
sys.path.append(os.path.abspath(scriptpath))
import MyModule

In case your python script gets updated and you don’t want to upload – use these statements for auto refresh. Bonus :)

%load_ext autoreload 
%autoreload 2

回答 13

只是为了将python文件导入另一个python文件

可以说我有一个具有显示功能的helper.py python文件,

def display():
    print("I'm working sundar gsv")

现在在app.py中,您可以使用显示功能,

import helper
helper.display()

输出,

I'm working sundar gsv

注意:无需指定.py扩展名。

Just to import python file in another python file

lets say I have helper.py python file which has a display function like,

def display():
    print("I'm working sundar gsv")

Now in app.py, you can use the display function,

import helper
helper.display()

The output,

I'm working sundar gsv

NOTE: No need to specify the .py extension.


回答 14

这听起来很疯狂,但是如果您只是要为其创建包装脚本,则可以仅创建指向要导入文件的符号链接。

This may sound crazy but you can just create a symbolic link to the file you want to import if you’re just creating a wrapper script to it.


回答 15

您也可以这样做: from filename import something

示例:from client import Client 请注意,您不需要.py .pyw .pyui扩展名。

You can also do this: from filename import something

example: from client import Client Note that you do not need the .py .pyw .pyui extension.


回答 16

这就是我从python文件中调用函数的方式,这对我来说可以灵活地调用任何函数。

import os, importlib, sys

def callfunc(myfile, myfunc, *args):
    pathname, filename = os.path.split(myfile)
    sys.path.append(os.path.abspath(pathname))
    modname = os.path.splitext(filename)[0]
    mymod = importlib.import_module(modname)
    result = getattr(mymod, myfunc)(*args)
    return result

result = callfunc("pathto/myfile.py", "myfunc", arg1, arg2)

This is how I did to call a function from a python file, that is flexible for me to call any functions.

import os, importlib, sys

def callfunc(myfile, myfunc, *args):
    pathname, filename = os.path.split(myfile)
    sys.path.append(os.path.abspath(pathname))
    modname = os.path.splitext(filename)[0]
    mymod = importlib.import_module(modname)
    result = getattr(mymod, myfunc)(*args)
    return result

result = callfunc("pathto/myfile.py", "myfunc", arg1, arg2)

回答 17

如上所述,有很多方法,但是我发现我只想导入他文件的内容,而不想要写行和输入其他模块。因此,我想出了一种方法来获取文件的内容,即使使用点语法(file.property)也是如此,而不是将导入的文件与您的文件合并。
首先,这是我要导入的文件,data.py

    testString= "A string literal to import and test with"


注意:您可以改用.txt扩展名。
在中mainfile.py,首先打开并获取内容。

    #!usr/bin/env python3
    Data=open('data.txt','r+').read()

现在,您已将内容作为字符串保存,但是尝试访问data.testString将导致错误,就像该类data的实例一样str,即使它确实具有属性testString,也无法实现您期望的效果。
接下来,创建一个类。例如(双关语意图),ImportedFile

    class ImportedFile:

并放入其中(带有适当的缩进):

    exec(data)


最后,data像这样重新分配:

    data=ImportedFile()

就是这样!就像访问其他模块一样进行访问,print(data.testString)将在控制台上输入内容A string literal to import and test with
但是,如果您from mod import *只想删除类,实例分配并取消缩进,则等效于exec

希望这会
有所帮助:)-Benji

There are many ways, as listed above, but I find that I just want to import he contents of a file, and don’t want to have to write lines and lines and have to import other modules. So, I came up with a way to get the contents of a file, even with the dot syntax (file.property) as opposed to merging the imported file with yours.
First of all, here is my file which I’ll import, data.py

    testString= "A string literal to import and test with"


Note: You could use the .txt extension instead.
In mainfile.py, start by opening and getting the contents.

    #!usr/bin/env python3
    Data=open('data.txt','r+').read()

Now you have the contents as a string, but trying to access data.testString will cause an error, as data is an instance of the str class, and even if it does have a property testString it will not do what you expected.
Next, create a class. For instance (pun intended), ImportedFile

    class ImportedFile:

And put this into it (with the appropriate indentation):

    exec(data)


And finally, re-assign data like so:

    data=ImportedFile()

And that’s it! Just access like you would for any-other module, typing print(data.testString) will print to the console A string literal to import and test with.
If, however, you want the equivalent of from mod import * just drop the class, instance assignment, and de-dent the exec.

Hope this helps:)
-Benji


回答 18

Python的一个非常未知的功能是能够导入zip文件:

library.zip
|-library
|--__init__.py

__init__.py软件包的文件包含以下内容:

def dummy():
    print 'Testing things out...'

我们可以编写另一个脚本,该脚本可以从zip存档中导入包。仅需要将zip文件添加到sys.path。

import sys
sys.path.append(r'library.zip')

import library

def run():
    library.dummy()

run()

One very unknown feature of Python is the ability to import zip files:

library.zip
|-library
|--__init__.py

The file __init__.py of the package contains the following:

def dummy():
    print 'Testing things out...'

We can write another script which can import a package from the zip archive. It is only necessary to add the zip file to the sys.path.

import sys
sys.path.append(r'library.zip')

import library

def run():
    library.dummy()

run()

Python中递增和递减运算符的行为

问题:Python中递增和递减运算符的行为

我注意到,可以对变量(如++count)应用预增减算符。它可以编译,但实际上并不会改变变量的值!

Python中预增/减运算符(++ /-)的行为是什么?

为什么Python会偏离C / C ++中看到的这些运算符的行为?

I notice that a pre-increment/decrement operator can be applied on a variable (like ++count). It compiles, but it does not actually change the value of the variable!

What is the behavior of the pre-increment/decrement operators (++/–) in Python?

Why does Python deviate from the behavior of these operators seen in C/C++?


回答 0

++不是运算符。它是两个+运算符。该+运营商的身份运营,这什么都不做。(澄清:the +-一元运算符仅对数字起作用,但是我假设您不会期望假设的++运算符对字符串起作用。)

++count

解析为

+(+count)

转化为

count

您必须使用稍长的+=运算符来完成您想做的事情:

count += 1

我怀疑++--运算符因一致性和简单性而被遗漏了。我不知道Guido van Rossum做出决定的确切论据,但我可以想象一些论点:

  • 更简单的解析。从技术上讲,解析++count是模糊的,因为它可能是++count(两个一元+经营者)一样容易,因为它可能是++count(一个一元++运算符)。它不是语法上的明显歧义,但确实存在。
  • 语言更简单。++只不过是的同义词+= 1。这是一种速记方法,因为C编译器很愚蠢,并且不知道如何优化大多数计算机所拥有a += 1inc指令。在优化编译器和字节码解释语言的这一天,通常不赞成在一种语言中添加运算符以允许程序员优化其代码,尤其是在像Python这样设计成一致且易读的语言中。
  • 令人困惑的副作用。带有++运算符的语言中一个常见的新手错误是将递增/递减运算符前后的差异(优先级和返回值)混合在一起,Python喜欢消除语言“陷阱”。该优先事项用C前置/后置增量是相当毛,和令人难以置信的容易陷入困境。

++ is not an operator. It is two + operators. The + operator is the identity operator, which does nothing. (Clarification: the + and - unary operators only work on numbers, but I presume that you wouldn’t expect a hypothetical ++ operator to work on strings.)

++count

Parses as

+(+count)

Which translates to

count

You have to use the slightly longer += operator to do what you want to do:

count += 1

I suspect the ++ and -- operators were left out for consistency and simplicity. I don’t know the exact argument Guido van Rossum gave for the decision, but I can imagine a few arguments:

  • Simpler parsing. Technically, parsing ++count is ambiguous, as it could be +, +, count (two unary + operators) just as easily as it could be ++, count (one unary ++ operator). It’s not a significant syntactic ambiguity, but it does exist.
  • Simpler language. ++ is nothing more than a synonym for += 1. It was a shorthand invented because C compilers were stupid and didn’t know how to optimize a += 1 into the inc instruction most computers have. In this day of optimizing compilers and bytecode interpreted languages, adding operators to a language to allow programmers to optimize their code is usually frowned upon, especially in a language like Python that is designed to be consistent and readable.
  • Confusing side-effects. One common newbie error in languages with ++ operators is mixing up the differences (both in precedence and in return value) between the pre- and post-increment/decrement operators, and Python likes to eliminate language “gotcha”-s. The precedence issues of pre-/post-increment in C are pretty hairy, and incredibly easy to mess up.

回答 1

当您想增加或减少时,通常需要对整数进行操作。像这样:

b++

但是在Python中,整数是不可变的。那是你不能改变他们。这是因为可以使用多个名称使用整数对象。尝试这个:

>>> b = 5
>>> a = 5
>>> id(a)
162334512
>>> id(b)
162334512
>>> a is b
True

上面的a和b实际上是同一对象。如果增加a,也将增加b。那不是你想要的。因此,您必须重新分配。像这样:

b = b + 1

或更简单:

b += 1

哪个将重新分配bb+1。那不是增量运算符,因为它不会增量b,而是重新分配它。

简而言之:Python在这里的行为有所不同,因为它不是C,也不是机器代码的底层包装,而是高级动态语言,在这种语言中,增量没有意义,也没有C所必需,例如,每次有循环时在哪里使用它们。

When you want to increment or decrement, you typically want to do that on an integer. Like so:

b++

But in Python, integers are immutable. That is you can’t change them. This is because the integer objects can be used under several names. Try this:

>>> b = 5
>>> a = 5
>>> id(a)
162334512
>>> id(b)
162334512
>>> a is b
True

a and b above are actually the same object. If you incremented a, you would also increment b. That’s not what you want. So you have to reassign. Like this:

b = b + 1

Or simpler:

b += 1

Which will reassign b to b+1. That is not an increment operator, because it does not increment b, it reassigns it.

In short: Python behaves differently here, because it is not C, and is not a low level wrapper around machine code, but a high-level dynamic language, where increments don’t make sense, and also are not as necessary as in C, where you use them every time you have a loop, for example.


回答 2

尽管其他答案在表明仅仅+做某事上是正确的(即,保留数字,如果是一个,则保持不变),但就他们不解释会发生什么而言,它们是不完整的。

确切地说,+xx.__pos__()++x求值x.__pos__().__pos__()

我可以想象一个非常奇怪的类结构(孩子们,不要在家做!),像这样:

class ValueKeeper(object):
    def __init__(self, value): self.value = value
    def __str__(self): return str(self.value)

class A(ValueKeeper):
    def __pos__(self):
        print 'called A.__pos__'
        return B(self.value - 3)

class B(ValueKeeper):
    def __pos__(self):
        print 'called B.__pos__'
        return A(self.value + 19)

x = A(430)
print x, type(x)
print +x, type(+x)
print ++x, type(++x)
print +++x, type(+++x)

While the others answers are correct in so far as they show what a mere + usually does (namely, leave the number as it is, if it is one), they are incomplete in so far as they don’t explain what happens.

To be exact, +x evaluates to x.__pos__() and ++x to x.__pos__().__pos__().

I could imagine a VERY weird class structure (Children, don’t do this at home!) like this:

class ValueKeeper(object):
    def __init__(self, value): self.value = value
    def __str__(self): return str(self.value)

class A(ValueKeeper):
    def __pos__(self):
        print 'called A.__pos__'
        return B(self.value - 3)

class B(ValueKeeper):
    def __pos__(self):
        print 'called B.__pos__'
        return A(self.value + 19)

x = A(430)
print x, type(x)
print +x, type(+x)
print ++x, type(++x)
print +++x, type(+++x)

回答 3

Python没有这些运算符,但是如果您确实需要它们,则可以编写具有相同功能的函数。

def PreIncrement(name, local={}):
    #Equivalent to ++name
    if name in local:
        local[name]+=1
        return local[name]
    globals()[name]+=1
    return globals()[name]

def PostIncrement(name, local={}):
    #Equivalent to name++
    if name in local:
        local[name]+=1
        return local[name]-1
    globals()[name]+=1
    return globals()[name]-1

用法:

x = 1
y = PreIncrement('x') #y and x are both 2
a = 1
b = PostIncrement('a') #b is 1 and a is 2

在函数内部,如果要更改局部变量,则必须添加locals()作为第二个参数,否则它将尝试更改全局变量。

x = 1
def test():
    x = 10
    y = PreIncrement('x') #y will be 2, local x will be still 10 and global x will be changed to 2
    z = PreIncrement('x', locals()) #z will be 11, local x will be 11 and global x will be unaltered
test()

使用这些功能,您还可以执行以下操作:

x = 1
print(PreIncrement('x'))   #print(x+=1) is illegal!

但是我认为以下方法更加清晰:

x = 1
x+=1
print(x)

减量运算符:

def PreDecrement(name, local={}):
    #Equivalent to --name
    if name in local:
        local[name]-=1
        return local[name]
    globals()[name]-=1
    return globals()[name]

def PostDecrement(name, local={}):
    #Equivalent to name--
    if name in local:
        local[name]-=1
        return local[name]+1
    globals()[name]-=1
    return globals()[name]+1

我在将javascript转换为python的模块中使用了这些功能。

Python does not have these operators, but if you really need them you can write a function having the same functionality.

def PreIncrement(name, local={}):
    #Equivalent to ++name
    if name in local:
        local[name]+=1
        return local[name]
    globals()[name]+=1
    return globals()[name]

def PostIncrement(name, local={}):
    #Equivalent to name++
    if name in local:
        local[name]+=1
        return local[name]-1
    globals()[name]+=1
    return globals()[name]-1

Usage:

x = 1
y = PreIncrement('x') #y and x are both 2
a = 1
b = PostIncrement('a') #b is 1 and a is 2

Inside a function you have to add locals() as a second argument if you want to change local variable, otherwise it will try to change global.

x = 1
def test():
    x = 10
    y = PreIncrement('x') #y will be 2, local x will be still 10 and global x will be changed to 2
    z = PreIncrement('x', locals()) #z will be 11, local x will be 11 and global x will be unaltered
test()

Also with these functions you can do:

x = 1
print(PreIncrement('x'))   #print(x+=1) is illegal!

But in my opinion following approach is much clearer:

x = 1
x+=1
print(x)

Decrement operators:

def PreDecrement(name, local={}):
    #Equivalent to --name
    if name in local:
        local[name]-=1
        return local[name]
    globals()[name]-=1
    return globals()[name]

def PostDecrement(name, local={}):
    #Equivalent to name--
    if name in local:
        local[name]-=1
        return local[name]+1
    globals()[name]-=1
    return globals()[name]+1

I used these functions in my module translating javascript to python.


回答 4

在Python中,与Common Lisp,Scheme或Ruby之类的语言相比,严格执行了表达式和语句之间的区别。

维基百科

因此,通过引入此类运算符,可以打破表达式/语句的拆分。

出于同样的原因,你不能写

if x = 0:
  y = 1

就像其他一些语言一样,这种语言没有保留。

In Python, a distinction between expressions and statements is rigidly enforced, in contrast to languages such as Common Lisp, Scheme, or Ruby.

Wikipedia

So by introducing such operators, you would break the expression/statement split.

For the same reason you can’t write

if x = 0:
  y = 1

as you can in some other languages where such distinction is not preserved.


回答 5

TL; DR

Python没有一元增减运算符(--/ ++)。相反,要增加值,请使用

a += 1

更多细节和陷阱

但是请注意这里。如果您来自C,即使在python中也是如此。在C的意义上,Python没有“变量”,而是python使用名称对象,并且在ints中是不可变的。

所以说你做

a = 1

这在python中的含义是:创建一个int具有值的类型的对象,1并将名称绑定a到该对象。的对象是的一个实例int具有值1,并且名称 a是指它。名称a和它引用的对象是不同的。

现在说你做

a += 1

由于ints是不可变的,因此这里发生的情况如下:

  1. 查找所a引用的对象(intID为0x559239eeb380
  2. 查找对象的值0x559239eeb380(为1
  3. 给该值加1(1 +1 = 2)
  4. 创建一个具有值的 int对象2(它具有对象id 0x559239eeb3a0
  5. 将名称重新绑定a到这个新对象
  6. 现在a引用对象,0x559239eeb3a0并且0x559239eeb380名称不再引用原始对象()a。如果没有其他名称引用原始对象,则稍后将对其进行垃圾回收。

自己尝试一下:

a = 1
print(hex(id(a)))
a += 1
print(hex(id(a)))

TL;DR

Python does not have unary increment/decrement operators (--/++). Instead, to increment a value, use

a += 1

More detail and gotchas

But be careful here. If you’re coming from C, even this is different in python. Python doesn’t have “variables” in the sense that C does, instead python uses names and objects, and in python ints are immutable.

so lets say you do

a = 1

What this means in python is: create an object of type int having value 1 and bind the name a to it. The object is an instance of int having value 1, and the name a refers to it. The name a and the object to which it refers are distinct.

Now lets say you do

a += 1

Since ints are immutable, what happens here is as follows:

  1. look up the object that a refers to (it is an int with id 0x559239eeb380)
  2. look up the value of object 0x559239eeb380 (it is 1)
  3. add 1 to that value (1 + 1 = 2)
  4. create a new int object with value 2 (it has object id 0x559239eeb3a0)
  5. rebind the name a to this new object
  6. Now a refers to object 0x559239eeb3a0 and the original object (0x559239eeb380) is no longer refered to by the name a. If there aren’t any other names refering to the original object it will be garbage collected later.

Give it a try yourself:

a = 1
print(hex(id(a)))
a += 1
print(hex(id(a)))

回答 6

是的,我也错过了++和-功能。几百万行c代码使这种思想深深地扎根在我的脑海中,而不是与之抗争……这是我拼凑而成的一类,实现了:

pre- and post-increment, pre- and post-decrement, addition,
subtraction, multiplication, division, results assignable
as integer, printable, settable.

这是:

class counter(object):
    def __init__(self,v=0):
        self.set(v)

    def preinc(self):
        self.v += 1
        return self.v
    def predec(self):
        self.v -= 1
        return self.v

    def postinc(self):
        self.v += 1
        return self.v - 1
    def postdec(self):
        self.v -= 1
        return self.v + 1

    def __add__(self,addend):
        return self.v + addend
    def __sub__(self,subtrahend):
        return self.v - subtrahend
    def __mul__(self,multiplier):
        return self.v * multiplier
    def __div__(self,divisor):
        return self.v / divisor

    def __getitem__(self):
        return self.v

    def __str__(self):
        return str(self.v)

    def set(self,v):
        if type(v) != int:
            v = 0
        self.v = v

您可以这样使用它:

c = counter()                          # defaults to zero
for listItem in myList:                # imaginary task
     doSomething(c.postinc(),listItem) # passes c, but becomes c+1

…已经有了c,您可以执行此操作…

c.set(11)
while c.predec() > 0:
    print c

….要不就…

d = counter(11)
while d.predec() > 0:
    print d

…并用于(重新)分配为整数…

c = counter(100)
d = c + 223 # assignment as integer
c = c + 223 # re-assignment as integer
print type(c),c # <type 'int'> 323

…这将使c保持为类型计数器:

c = counter(100)
c.set(c + 223)
print type(c),c # <class '__main__.counter'> 323

编辑:

然后还有一些意想不到的(并且完全是不想要的)行为

c = counter(42)
s = '%s: %d' % ('Expecting 42',c) # but getting non-numeric exception
print s

…因为在该元组中,没有使用getitem(),而是将对对象的引用传递给格式函数。叹。所以:

c = counter(42)
s = '%s: %d' % ('Expecting 42',c.v) # and getting 42.
print s

…或更确切地说,是我们实际上想要发生的事情,尽管冗长性以实际形式相反表示(c.v改为使用)。

c = counter(42)
s = '%s: %d' % ('Expecting 42',c.__getitem__()) # and getting 42.
print s

Yeah, I missed ++ and — functionality as well. A few million lines of c code engrained that kind of thinking in my old head, and rather than fight it… Here’s a class I cobbled up that implements:

pre- and post-increment, pre- and post-decrement, addition,
subtraction, multiplication, division, results assignable
as integer, printable, settable.

Here ’tis:

class counter(object):
    def __init__(self,v=0):
        self.set(v)

    def preinc(self):
        self.v += 1
        return self.v
    def predec(self):
        self.v -= 1
        return self.v

    def postinc(self):
        self.v += 1
        return self.v - 1
    def postdec(self):
        self.v -= 1
        return self.v + 1

    def __add__(self,addend):
        return self.v + addend
    def __sub__(self,subtrahend):
        return self.v - subtrahend
    def __mul__(self,multiplier):
        return self.v * multiplier
    def __div__(self,divisor):
        return self.v / divisor

    def __getitem__(self):
        return self.v

    def __str__(self):
        return str(self.v)

    def set(self,v):
        if type(v) != int:
            v = 0
        self.v = v

You might use it like this:

c = counter()                          # defaults to zero
for listItem in myList:                # imaginary task
     doSomething(c.postinc(),listItem) # passes c, but becomes c+1

…already having c, you could do this…

c.set(11)
while c.predec() > 0:
    print c

….or just…

d = counter(11)
while d.predec() > 0:
    print d

…and for (re-)assignment into integer…

c = counter(100)
d = c + 223 # assignment as integer
c = c + 223 # re-assignment as integer
print type(c),c # <type 'int'> 323

…while this will maintain c as type counter:

c = counter(100)
c.set(c + 223)
print type(c),c # <class '__main__.counter'> 323

EDIT:

And then there’s this bit of unexpected (and thoroughly unwanted) behavior,

c = counter(42)
s = '%s: %d' % ('Expecting 42',c) # but getting non-numeric exception
print s

…because inside that tuple, getitem() isn’t what used, instead a reference to the object is passed to the formatting function. Sigh. So:

c = counter(42)
s = '%s: %d' % ('Expecting 42',c.v) # and getting 42.
print s

…or, more verbosely, and explicitly what we actually wanted to happen, although counter-indicated in actual form by the verbosity (use c.v instead)…

c = counter(42)
s = '%s: %d' % ('Expecting 42',c.__getitem__()) # and getting 42.
print s

回答 7

python中没有像C之类的语言中的post / pre增量/减量运算符。

我们可以看到++--随着多个符号成倍增加,就像我们在数学(-1)*(-1)=(+1)中一样。

例如

---count

解析为

-(-(-count)))

转化为

-(+count)

因为,-符号与-符号的乘积为+

最后,

-count

There are no post/pre increment/decrement operators in python like in languages like C.

We can see ++ or -- as multiple signs getting multiplied, like we do in maths (-1) * (-1) = (+1).

E.g.

---count

Parses as

-(-(-count)))

Which translates to

-(+count)

Because, multiplication of - sign with - sign is +

And finally,

-count

回答 8

在python 3.8+中,您可以执行以下操作:

(a:=a+1) #same as a++

您可以对此进行很多思考。

>>> a = 0
>>> while (a:=a+1) < 5:
    print(a)


1
2
3
4

或者,如果您想使用更复杂的语法编写东西(目标不是优化):

>>> del a
>>> while (a := (a if 'a' in locals() else 0) + 1) < 5:
    print(a)


1
2
3
4

如果不存在任何错误,它将很好地返回0,然后将其设置为1

In python 3.8+ you can do :

(a:=a+1) #same as a++

You can do a lot of thinks with this.

>>> a = 0
>>> while (a:=a+1) < 5:
    print(a)


1
2
3
4

Or if you want write somthing with more sophisticated syntaxe (the goal is not optimization):

>>> del a
>>> while (a := (a if 'a' in locals() else 0) + 1) < 5:
    print(a)


1
2
3
4

It well return 0 if a dosn’t exist without errors, and then will set it to 1


无论OS /路径格式如何,都从路径中提取文件名

问题:无论OS /路径格式如何,都从路径中提取文件名

无论使用哪种操作系统或路径格式,我都可以使用哪个Python库从路径提取文件名?

例如,我希望所有这些路径返回我c

a/b/c/
a/b/c
\a\b\c
\a\b\c\
a\b\c
a/b/../../a/b/c/
a/b/../../a/b/c

Which Python library can I use to extract filenames from paths, no matter what the operating system or path format could be?

For example, I’d like all of these paths to return me c:

a/b/c/
a/b/c
\a\b\c
\a\b\c\
a\b\c
a/b/../../a/b/c/
a/b/../../a/b/c

回答 0

使用os.path.splitos.path.basename建议使用并非在所有情况下都行得通:如果您在Linux上运行脚本并尝试处理经典的Windows样式路径,它将失败。

Windows路径可以使用反斜杠或正斜杠作为路径分隔符。因此,该ntpath模块(在Windows上运行时等效于os.path)将适用于所有平台上的所有(1)路径。

import ntpath
ntpath.basename("a/b/c")

当然,如果文件以斜杠结尾,则基名将为空,因此请使用您自己的函数来处理它:

def path_leaf(path):
    head, tail = ntpath.split(path)
    return tail or ntpath.basename(head)

验证:

>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...     'a/b/../../a/b/c/', 'a/b/../../a/b/c']
>>> [path_leaf(path) for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']


(1)有一个警告:Linux文件名可能包含反斜杠。因此,在Linux上,r'a/b\c'始终引用文件夹b\c中的a文件,而在Windows上,始终引用c文件b夹的子文件夹中的a文件。因此,在路径中同时使用正斜杠和反斜杠时,您需要了解关联的平台才能正确解释它。实际上,通常可以安全地假定它是Windows路径,因为Linux文件名中很少使用反斜杠,但是在编写代码时请记住这一点,以免造成意外的安全漏洞。

Using os.path.split or os.path.basename as others suggest won’t work in all cases: if you’re running the script on Linux and attempt to process a classic windows-style path, it will fail.

Windows paths can use either backslash or forward slash as path separator. Therefore, the ntpath module (which is equivalent to os.path when running on windows) will work for all(1) paths on all platforms.

import ntpath
ntpath.basename("a/b/c")

Of course, if the file ends with a slash, the basename will be empty, so make your own function to deal with it:

def path_leaf(path):
    head, tail = ntpath.split(path)
    return tail or ntpath.basename(head)

Verification:

>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...     'a/b/../../a/b/c/', 'a/b/../../a/b/c']
>>> [path_leaf(path) for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']


(1) There’s one caveat: Linux filenames may contain backslashes. So on linux, r'a/b\c' always refers to the file b\c in the a folder, while on Windows, it always refers to the c file in the b subfolder of the a folder. So when both forward and backward slashes are used in a path, you need to know the associated platform to be able to interpret it correctly. In practice it’s usually safe to assume it’s a windows path since backslashes are seldom used in Linux filenames, but keep this in mind when you code so you don’t create accidental security holes.


回答 1

实际上,有一个函数可以完全返回您想要的

import os
print(os.path.basename(your_path))

Actually, there’s a function that returns exactly what you want

import os
print(os.path.basename(your_path))

回答 2

os.path.split 是您要寻找的功能

head, tail = os.path.split("/tmp/d/a.dat")

>>> print(tail)
a.dat
>>> print(head)
/tmp/d

os.path.split is the function you are looking for

head, tail = os.path.split("/tmp/d/a.dat")

>>> print(tail)
a.dat
>>> print(head)
/tmp/d

回答 3

在python 3中

>>> from pathlib import Path    
>>> Path("/tmp/d/a.dat").name
'a.dat'

In python 3

>>> from pathlib import Path    
>>> Path("/tmp/d/a.dat").name
'a.dat'

回答 4

import os
head, tail = os.path.split('path/to/file.exe')

尾部就是您想要的文件名。

有关详细信息,请参见python os模块文档

import os
head, tail = os.path.split('path/to/file.exe')

tail is what you want, the filename.

See python os module docs for detail


回答 5

import os
file_location = '/srv/volume1/data/eds/eds_report.csv'
file_name = os.path.basename(file_location )  #eds_report.csv
location = os.path.dirname(file_location )    #/srv/volume1/data/eds
import os
file_location = '/srv/volume1/data/eds/eds_report.csv'
file_name = os.path.basename(file_location )  #eds_report.csv
location = os.path.dirname(file_location )    #/srv/volume1/data/eds

回答 6

在您的示例中,您还需要从右侧右侧去除斜线以返回c

>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'

第二级:

>>> os.path.filename(os.path.dirname(path))
'b'

更新:我认为lazyr已经提供了正确的答案。我的代码不适用于unix系统上类似Windows的路径,反之亦然,不适用于Windows系统上类似unix的路径。

In your example you will also need to strip slash from right the right side to return c:

>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'

Second level:

>>> os.path.filename(os.path.dirname(path))
'b'

update: I think lazyr has provided the right answer. My code will not work with windows-like paths on unix systems and vice versus with unix-like paths on windows system.


回答 7

fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]

这将返回:paint.exe

根据您的路径或操作系统更改分割功能的sep值。

fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]

this will return : paint.exe

change the sep value of the split function regarding your path or OS.


回答 8

如果要自动获取文件名,可以执行

import glob

for f in glob.glob('/your/path/*'):
    print(os.path.split(f)[-1])

If you want to get the filename automatically you can do

import glob

for f in glob.glob('/your/path/*'):
    print(os.path.split(f)[-1])

回答 9

如果您的文件路径不是以“ /”结尾并且目录以“ /”分隔,则使用以下代码。众所周知,路径通常不以“ /”结尾。

import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))

但是在某些情况下,例如URL以“ /”结尾,然后使用以下代码

import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))

但是,当您的路径通常在Windows路径中以“ \”分隔时,则可以使用以下代码

import os
path_str = "c:\\var\www\index.html"
print(os.path.basename(path_str))

import os
path_str = "c:\\home\some_str\last_str\\"
split_path = path_str.rsplit("\\",1)
print(os.path.basename(split_path[0]))

您可以通过检查OS类型将两者组合为一个功能并返回结果。

If your file path not ended with “/” and directories separated by “/” then use the following code. As we know generally path doesn’t end with “/”.

import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))

But in some cases like URLs end with “/” then use the following code

import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))

but when your path sperated by “\” which you generally find in windows paths then you can use the following codes

import os
path_str = "c:\\var\www\index.html"
print(os.path.basename(path_str))

import os
path_str = "c:\\home\some_str\last_str\\"
split_path = path_str.rsplit("\\",1)
print(os.path.basename(split_path[0]))

You can combine both into one function by check OS type and return the result.


回答 10

这适用于Linux和Windows,以及标准库

paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
         'a/b/../../a/b/c/', 'a/b/../../a/b/c']

def path_leaf(path):
    return path.strip('/').strip('\\').split('/')[-1].split('\\')[-1]

[path_leaf(path) for path in paths]

结果:

['c', 'c', 'c', 'c', 'c', 'c', 'c']

This is working for linux and windows as well with standard library

paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
         'a/b/../../a/b/c/', 'a/b/../../a/b/c']

def path_leaf(path):
    return path.strip('/').strip('\\').split('/')[-1].split('\\')[-1]

[path_leaf(path) for path in paths]

Results:

['c', 'c', 'c', 'c', 'c', 'c', 'c']

回答 11

这是仅用于正则表达式的解决方案,它似乎可与任何OS上的任何OS路径一起使用。

不需要其他模块,也不需要预处理:

import re

def extract_basename(path):
  """Extracts basename of a given path. Should Work with any OS Path on any OS"""
  basename = re.search(r'[^\\/]+(?=[\\/]?$)', path)
  if basename:
    return basename.group(0)


paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
         'a/b/../../a/b/c/', 'a/b/../../a/b/c']

print([extract_basename(path) for path in paths])
# ['c', 'c', 'c', 'c', 'c', 'c', 'c']


extra_paths = ['C:\\', 'alone', '/a/space in filename', 'C:\\multi\nline']

print([extract_basename(path) for path in extra_paths])
# ['C:', 'alone', 'space in filename', 'multi\nline']

更新:

如果您只想要一个潜在的文件名(如果存在)(即/a/b/dir,也是如此c:\windows\),则将正则表达式更改为:r'[^\\/]+(?![\\/])$'。对于“正则表达式挑战”,这会将某种斜杠的正向正向查找更改为负向正向查找,导致以所述斜杠结尾的路径名不返回任何内容,而不返回路径名中的最后一个子目录。当然,不能保证潜在的文件名实际上是指文件,并且为此os.path.is_dir()os.path.is_file()将需要使用。

这将匹配如下:

/a/b/c/             # nothing, pathname ends with the dir 'c'
c:\windows\         # nothing, pathname ends with the dir 'windows'
c:hello.txt         # matches potential filename 'hello.txt'
~it_s_me/.bashrc    # matches potential filename '.bashrc'
c:\windows\system32 # matches potential filename 'system32', except
                    # that is obviously a dir. os.path.is_dir()
                    # should be used to tell us for sure

可以在这里测试正则表达式。

Here’s a regex-only solution, which seems to work with any OS path on any OS.

No other module is needed, and no preprocessing is needed either :

import re

def extract_basename(path):
  """Extracts basename of a given path. Should Work with any OS Path on any OS"""
  basename = re.search(r'[^\\/]+(?=[\\/]?$)', path)
  if basename:
    return basename.group(0)


paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
         'a/b/../../a/b/c/', 'a/b/../../a/b/c']

print([extract_basename(path) for path in paths])
# ['c', 'c', 'c', 'c', 'c', 'c', 'c']


extra_paths = ['C:\\', 'alone', '/a/space in filename', 'C:\\multi\nline']

print([extract_basename(path) for path in extra_paths])
# ['C:', 'alone', 'space in filename', 'multi\nline']

Update:

If you only want a potential filename, if present (i.e., /a/b/ is a dir and so is c:\windows\), change the regex to: r'[^\\/]+(?![\\/])$' . For the “regex challenged,” this changes the positive forward lookahead for some sort of slash to a negative forward lookahead, causing pathnames that end with said slash to return nothing instead of the last sub-directory in the pathname. Of course there is no guarantee that the potential filename actually refers to a file and for that os.path.is_dir() or os.path.is_file() would need to be employed.

This will match as follows:

/a/b/c/             # nothing, pathname ends with the dir 'c'
c:\windows\         # nothing, pathname ends with the dir 'windows'
c:hello.txt         # matches potential filename 'hello.txt'
~it_s_me/.bashrc    # matches potential filename '.bashrc'
c:\windows\system32 # matches potential filename 'system32', except
                    # that is obviously a dir. os.path.is_dir()
                    # should be used to tell us for sure

The regex can be tested here.


回答 12

也许只是我的一站式解决方案,而没有重要的新特性(关于创建临时文件的临时文件:D)

import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1] 

获取的值abc.name将是这样的字符串:'/tmp/tmpks5oksk7' 所以我可以用/空格替换.replace("/", " "),然后调用split()。那将返回一个列表,我得到列表的最后一个元素[-1]

无需导入任何模块。

Maybe just my all in one solution without important some new(regard the tempfile for creating temporary files :D )

import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1] 

Getting the values of abc.name will be a string like this: '/tmp/tmpks5oksk7' So I can replace the / with a space .replace("/", " ") and then call split(). That will return a list and I get the last element of the list with [-1]

No need to get any module imported.


回答 13

我从未见过双反斜线路径,它们是否存在?python模块的内置功能对此os失败。其他所有工作方式,以及您对os.path.normpath()以下事项的警告:

paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...     'a/b/../../a/b/c/', 'a/b/../../a/b/c', 'a/./b/c', 'a\b/c']
for path in paths:
    os.path.basename(os.path.normpath(path))

I have never seen double-backslashed paths, are they existing? The built-in feature of python module os fails for those. All others work, also the caveat given by you with os.path.normpath():

paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...     'a/b/../../a/b/c/', 'a/b/../../a/b/c', 'a/./b/c', 'a\b/c']
for path in paths:
    os.path.basename(os.path.normpath(path))

回答 14

Windows分隔符可以在Unix文件名或Windows路径中。Unix分隔符只能存在于Unix路径中。Unix分隔符的存在指示非Windows路径。

以下将通过操作系统特定的分隔符剥离(剪切尾随的分隔符),然后分割并返回最右边的值。这很丑陋,但基于上面的假设很简单。如果假设不正确,请更新,我将更新此回复以匹配更准确的条件。

a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]

样例代码:

b = ['a/b/c/','a/b/c','\\a\\b\\c','\\a\\b\\c\\','a\\b\\c','a/b/../../a/b/c/','a/b/../../a/b/c']

for a in b:

    print (a, a.rstrip("\\" if a.count("/") == 0 else '/').split("\\" if a.count("/") == 0 else '/')[-1])

The Windows separator can be in a Unix filename or Windows Path. The Unix separator can only exist in the Unix path. The presence of a Unix separator indicates a non-Windows path.

The following will strip (cut trailing separator) by the OS specific separator, then split and return the rightmost value. It’s ugly, but simple based on the assumption above. If the assumption is incorrect, please update and I will update this response to match the more accurate conditions.

a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]

sample code:

b = ['a/b/c/','a/b/c','\\a\\b\\c','\\a\\b\\c\\','a\\b\\c','a/b/../../a/b/c/','a/b/../../a/b/c']

for a in b:

    print (a, a.rstrip("\\" if a.count("/") == 0 else '/').split("\\" if a.count("/") == 0 else '/')[-1])

回答 15

为了完整起见,这是pathlibpython 3.2+ 的解决方案:

>>> from pathlib import PureWindowsPath

>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...          'a/b/../../a/b/c/', 'a/b/../../a/b/c']

>>> [PureWindowsPath(path).name for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']

这适用于Windows和Linux。

For completeness sake, here is the pathlib solution for python 3.2+:

>>> from pathlib import PureWindowsPath

>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c', 
...          'a/b/../../a/b/c/', 'a/b/../../a/b/c']

>>> [PureWindowsPath(path).name for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']

This works on both Windows and Linux.


回答 16

在Python 2和3中,都使用pathlib2模块:

import posixpath  # to generate unix paths
from pathlib2 import PurePath, PureWindowsPath, PurePosixPath

def path2unix(path, nojoin=True, fromwinpath=False):
    """From a path given in any format, converts to posix path format
    fromwinpath=True forces the input path to be recognized as a Windows path (useful on Unix machines to unit test Windows paths)"""
    if not path:
        return path
    if fromwinpath:
        pathparts = list(PureWindowsPath(path).parts)
    else:
        pathparts = list(PurePath(path).parts)
    if nojoin:
        return pathparts
    else:
        return posixpath.join(*pathparts)

用法:

In [9]: path2unix('lala/lolo/haha.dat')
Out[9]: ['lala', 'lolo', 'haha.dat']

In [10]: path2unix(r'C:\lala/lolo/haha.dat')
Out[10]: ['C:\\', 'lala', 'lolo', 'haha.dat']

In [11]: path2unix(r'C:\lala/lolo/haha.dat') # works even with malformatted cases mixing both Windows and Linux path separators
Out[11]: ['C:\\', 'lala', 'lolo', 'haha.dat']

与您的测试用例:

In [12]: testcase = paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
    ...: ...     'a/b/../../a/b/c/', 'a/b/../../a/b/c']

In [14]: for t in testcase:
    ...:     print(path2unix(t)[-1])
    ...:
    ...:
c
c
c
c
c
c
c

这里的想法是将所有路径转换为的统一内部表示形式pathlib2,具体取决于平台而使用不同的解码器。幸运的是,它pathlib2包括一个可PurePath在任何路径上工作的通用解码器。如果此方法无效,则可以使用强制识别Windows路径fromwinpath=True。这会将输入字符串分成多个部分,最后一个是您要查找的叶子,因此是path2unix(t)[-1]

如果为参数nojoin=False,则路径将重新加入,以便输出只是转换为Unix格式的输入字符串,这对于跨平台比较子路径很有用。

In both Python 2 and 3, using the module pathlib2:

import posixpath  # to generate unix paths
from pathlib2 import PurePath, PureWindowsPath, PurePosixPath

def path2unix(path, nojoin=True, fromwinpath=False):
    """From a path given in any format, converts to posix path format
    fromwinpath=True forces the input path to be recognized as a Windows path (useful on Unix machines to unit test Windows paths)"""
    if not path:
        return path
    if fromwinpath:
        pathparts = list(PureWindowsPath(path).parts)
    else:
        pathparts = list(PurePath(path).parts)
    if nojoin:
        return pathparts
    else:
        return posixpath.join(*pathparts)

Usage:

In [9]: path2unix('lala/lolo/haha.dat')
Out[9]: ['lala', 'lolo', 'haha.dat']

In [10]: path2unix(r'C:\lala/lolo/haha.dat')
Out[10]: ['C:\\', 'lala', 'lolo', 'haha.dat']

In [11]: path2unix(r'C:\lala/lolo/haha.dat') # works even with malformatted cases mixing both Windows and Linux path separators
Out[11]: ['C:\\', 'lala', 'lolo', 'haha.dat']

With your testcase:

In [12]: testcase = paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
    ...: ...     'a/b/../../a/b/c/', 'a/b/../../a/b/c']

In [14]: for t in testcase:
    ...:     print(path2unix(t)[-1])
    ...:
    ...:
c
c
c
c
c
c
c

The idea here is to convert all paths into the unified internal representation of pathlib2, with different decoders depending on the platform. Fortunately, pathlib2 includes a generic decoder called PurePath that should work on any path. In case this does not work, you can force the recognition of windows path using fromwinpath=True. This will split the input string into parts, the last one is the leaf you are looking for, hence the path2unix(t)[-1].

If the argument nojoin=False, the path will be joined back, so that the output is simply the input string converted to a Unix format, which can be useful to compare subpaths across platforms.


Python的__init__和self是做什么的?

问题:Python的__init__和self是做什么的?

我正在学习Python编程语言,遇到了一些我不太了解的东西。

用类似的方法:

def method(self, blah):
    def __init__(?):
        ....
    ....

怎么self办?这是什么意思?它是强制性的吗?

__init__方法做什么?为什么有必要?(等等。)

我认为它们可能是OOP构造,但我不太了解。

I’m learning the Python programming language and I’ve came across something I don’t fully understand.

In a method like:

def method(self, blah):
    def __init__(?):
        ....
    ....

What does self do? What is it meant to be? Is it mandatory?

What does the __init__ method do? Why is it necessary? (etc.)

I think they might be OOP constructs, but I don’t know very much.


回答 0

在此代码中:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

self变量表示对象本身的实例。大多数面向对象的语言将此作为隐藏参数传递给在对象上定义的方法。Python没有。您必须明确声明它。创建A类的实例并调用其方法时,它将自动传递,如…

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

__init__方法大致代表了Python中的构造函数。调用时,A()Python为您创建一个对象,并将其作为第一个参数传递给__init__方法。任何其他参数(例如A(24, 'Hello'))也将作为参数传递-在这种情况下,会引发异常,因为构造函数不期望它们。

In this code:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

… the self variable represents the instance of the object itself. Most object-oriented languages pass this as a hidden parameter to the methods defined on an object; Python does not. You have to declare it explicitly. When you create an instance of the A class and call its methods, it will be passed automatically, as in …

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

The __init__ method is roughly what represents a constructor in Python. When you call A() Python creates an object for you, and passes it as the first parameter to the __init__ method. Any additional parameters (e.g., A(24, 'Hello')) will also get passed as arguments–in this case causing an exception to be raised, since the constructor isn’t expecting them.


回答 1

是的,您是对的,这些是oop结构。

__init__是一个类的构造函数。该self参数是指对象的实例(如this在C ++中)。

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

__init__分配对象的内存时将调用该方法:

x = Point(1,2)

self如果要将值与对象保持在一起,则在对象的方法内使用参数很重要。例如,如果您实现如下__init__方法:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

您的xy参数将存储在堆栈中的变量中,并且当init方法超出范围时将被丢弃。将这些变量设置为self._x并将self._y这些变量设置为Point对象的成员(在对象的生存期内可访问)。

Yep, you are right, these are oop constructs.

__init__ is the constructor for a class. The self parameter refers to the instance of the object (like this in C++).

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

The __init__ method gets called when memory for the object is allocated:

x = Point(1,2)

It is important to use the self parameter inside an object’s method if you want to persist the value with the object. If, for instance, you implement the __init__ method like this:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

Your x and y parameters would be stored in variables on the stack and would be discarded when the init method goes out of scope. Setting those variables as self._x and self._y sets those variables as members of the Point object (accessible for the lifetime of the object).


回答 2

简短的说明性示例

希望对您有所帮助,这是我用来理解在类内部声明的变量与在__init__函数内部声明的变量之间的区别的一个简单示例:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

输出:

345
123

A brief illustrative example

In the hope it might help a little, here’s a simple example I used to understand the difference between a variable declared inside a class, and a variable declared inside an __init__ function:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

Output:

345
123

回答 3

简而言之:

  1. self正如它暗示的那样,它指向自身 -调用该方法的对象。也就是说,如果您有N个对象调用该方法,则将self.a为N个对象中的每一个引用变量的单独实例。想象a每个对象的N个变量副本
  2. __init__在其他OOP语言(例如C ++ / Java)中称为构造函数。基本思想是它是一种特殊的方法,当创建该Class的对象时会自动调用该方法

In short:

  1. self as it suggests, refers to itself– the object which has called the method. That is, if you have N objects calling the method, then self.a will refer to a separate instance of the variable for each of the N objects. Imagine N copies of the variable a for each object
  2. __init__ is what is called as a constructor in other OOP languages such as C++/Java. The basic idea is that it is a special method which is automatically called when an object of that Class is created

回答 4

__init__确实像构造函数。如果希望它们充当非静态方法,则需要将“ self”作为第一个参数传递给任何类函数。“ self”是您的类的实例变量。

__init__ does act like a constructor. You’ll need to pass “self” to any class functions as the first argument if you want them to behave as non-static methods. “self” are instance variables for your class.


回答 5

试用此代码。希望它能帮助像我这样的许多C程序员学习Py。

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

输出:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay

Try out this code. Hope it helps many C programmers like me to Learn Py.

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

Output:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay


回答 6

类对象支持两种操作:属性引用和实例化

属性引用使用Python中所有属性引用使用的标准语法:obj.name。有效属性名称是创建类对象时在类命名空间中的所有名称。因此,如果类定义如下所示:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

then MyClass.iMyClass.f是有效的属性引用,分别返回整数和函数对象。类属性也可以分配给它,因此您可以MyClass.i通过赋值来更改其值。__doc__也是有效的属性,返回属于该类的文档字符串:“简单示例类”。

类实例化使用函数表示法。只是假装类对象是一个无参数函数,它将返回该类的新实例。例如:

x = MyClass()

所述实例化操作(“呼叫”一类对象)来创建一个空对象。许多类喜欢创建具有定制为特定初始状态的实例的对象。因此,一个类可以定义一个名为的特殊方法__init__(),如下所示:

def __init__(self):
    self.data = []

当类定义__init__()方法时,类实例化将自动__init__()为新创建的类实例调用。因此,在此示例中,可以通过以下方式获取新的初始化实例:

x = MyClass()

当然,该__init__()方法可能具有更大的灵活性。在这种情况下,提供给类实例化运算符的参数将传递给__init__()。例如,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

摘自最终对我最大的帮助的官方文档


这是我的例子

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

创建Bill类的实例时:

purchase = Bill(5,6,7)

你得到:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)

Class objects support two kinds of operations: attribute references and instantiation

Attribute references use the standard syntax used for all attribute references in Python: obj.name. Valid attribute names are all the names that were in the class’s namespace when the class object was created. So, if the class definition looked like this:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

then MyClass.i and MyClass.f are valid attribute references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of MyClass.i by assignment. __doc__ is also a valid attribute, returning the docstring belonging to the class: “A simple example class”.

Class instantiation uses function notation. Just pretend that the class object is a parameterless function that returns a new instance of the class. For example:

x = MyClass()

The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named __init__(), like this:

def __init__(self):
    self.data = []

When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly-created class instance. So in this example, a new, initialized instance can be obtained by:

x = MyClass()

Of course, the __init__() method may have arguments for greater flexibility. In that case, arguments given to the class instantiation operator are passed on to __init__(). For example,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

Taken from official documentation which helped me the most in the end.


Here is my example

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

When you create instance of class Bill:

purchase = Bill(5,6,7)

You get:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)

回答 7

自己弄不清楚这个问题。即使在这里阅读答案。

要正确理解__init__方法,您需要了解自己。

自我参数

__init__方法接受的参数为:

def __init__(self, arg1, arg2):

但是我们实际上只传递了两个参数:

instance = OurClass('arg1', 'arg2')

多余的参数从何而来?

当我们访问对象的属性时,我们按名称(或按引用)进行操作。这里的实例是对我们新对象的引用。我们使用instance.printargs访问实例对象的printargs方法。

为了从__init__方法内部访问对象属性,我们需要对对象的引用。

每当调用方法时,对主对象的引用都会作为第一个参数传递。按照惯例,您总是将第一个参数称为方法自身。

这意味着__init__我们可以执行以下方法:

self.arg1 = arg1
self.arg2 = arg2

在这里,我们在对象上设置属性。您可以通过执行以下操作来验证这一点:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

这样的值称为对象属性。在这里,该__init__方法设置实例的arg1和arg2属性。

来源:http : //www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method

Had trouble undestanding this myself. Even after reading the answers here.

To properly understand the __init__ method you need to understand self.

The self Parameter

The arguments accepted by the __init__ method are :

def __init__(self, arg1, arg2):

But we only actually pass it two arguments :

instance = OurClass('arg1', 'arg2')

Where has the extra argument come from ?

When we access attributes of an object we do it by name (or by reference). Here instance is a reference to our new object. We access the printargs method of the instance object using instance.printargs.

In order to access object attributes from within the __init__ method we need a reference to the object.

Whenever a method is called, a reference to the main object is passed as the first argument. By convention you always call this first argument to your methods self.

This means in the __init__ method we can do :

self.arg1 = arg1
self.arg2 = arg2

Here we are setting attributes on the object. You can verify this by doing the following :

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

values like this are known as object attributes. Here the __init__ method sets the arg1 and arg2 attributes of the instance.

source: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method


回答 8

请注意,self实际上它可以是任何有效的python标识符。例如,我们可以从Chris B的示例中轻松编写:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

它的工作原理完全一样。但是,建议使用self,因为其他pythoner会更容易识别它。

note that self could actually be any valid python identifier. For example, we could just as easily write, from Chris B’s example:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

and it would work exactly the same. It is however recommended to use self because other pythoners will recognize it more easily.


回答 9

基本上,在同一类的多个函数中使用变量时,需要使用’self’关键字。至于init,它用于设置默认值,以防该类中没有其他函数被调用。

Basically, you need to use the ‘self’ keyword when using a variable in multiple functions within the same class. As for init, it’s used to setup default values incase no other functions from within that class are called.


回答 10

  1. __init__本质上是一个函数,一旦创建并与相应的类匹配,该函数将“初始化” / “激活”特定对象的类的属性。
  2. self 表示将继承这些属性的对象。
  1. __init__ is basically a function which will “initialize”/“activate” the properties of the class for a specific object, once created and matched to the corresponding class..
  2. self represents that object which will inherit those properties.

回答 11

“自我”是对类实例的引用

class foo:
    def bar(self):
            print "hi"

现在我们可以创建foo的实例并对其调用方法,在这种情况下,Python将添加self参数:

f = foo()
f.bar()

但是,如果方法调用不在类实例的上下文中,则也可以传递它,下面的代码执行相同的操作

f = foo()
foo.bar(f)

有趣的是,变量名“ self”只是一个约定。下面的定义将完全相同。.尽管说过,这是非常严格的约定,应该始终遵循,但是它确实说明了语言的灵活性。

class foo:
    def bar(s):
            print "hi"

The ‘self’ is a reference to the class instance

class foo:
    def bar(self):
            print "hi"

Now we can create an instance of foo and call the method on it, the self parameter is added by Python in this case:

f = foo()
f.bar()

But it can be passed in as well if the method call isn’t in the context of an instance of the class, the code below does the same thing

f = foo()
foo.bar(f)

Interestingly the variable name ‘self’ is just a convention. The below definition will work exactly the same.. Having said that it is very strong convention which should be followed always, but it does say something about flexible nature of the language

class foo:
    def bar(s):
            print "hi"

回答 12

只是演示的问题。

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class

Just a demo for the question.

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class

回答 13

在此代码中:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

在此__init__充当类的构造函数,并在实例化对象时调用此函数。self表示实例化对象。

c = Cat('Kitty')
c.info()

以上语句的结果如下:

I am a cat and I am called Kitty

In this code:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

Here __init__ acts as a constructor for the class and when an object is instantiated, this function is called. self represents the instantiating object.

c = Cat('Kitty')
c.info()

The result of the above statements will be as follows:

I am a cat and I am called Kitty

回答 14

什么是自我呢?这是什么意思?是强制性的吗?

每个类方法(包括init)的第一个参数始终是对该类当前实例的引用。按照惯例,该参数始终命名为self。在init方法中,self指的是新创建的对象;在其他类方法中,它引用其方法被调用的实例。

Python 不会强迫您使用self ”。您可以为其指定任何名称。但是请记住,方法定义中的第一个参数是对对象的引用。Python self为您将参数添加到列表中。调用方法时不需要包含它。如果您没有提供self in init方法,则会收到错误消息

TypeError: __init___() takes no arguments (1 given)

什么是初始化方法吗?为什么有必要?(等等。)

init是初始化的缩写。它是一个构造函数,当您创建类的实例时会调用该构造函数,而不必这样做。但是通常我们的做法是编写用于设置对象默认状态的init方法。如果您最初不愿设置对象的任何状态,则无需编写此方法。

What does self do? What is it meant to be? Is it mandatory?

The first argument of every class method, including init, is always a reference to the current instance of the class. By convention, this argument is always named self. In the init method, self refers to the newly created object; in other class methods, it refers to the instance whose method was called.

Python doesn’t force you on usingself“. You can give it any name you want. But remember the first argument in a method definition is a reference to the object. Python adds the self argument to the list for you; you do not need to include it when you call the methods. if you didn’t provide self in init method then you will get an error

TypeError: __init___() takes no arguments (1 given)

What does the init method do? Why is it necessary? (etc.)

init is short for initialization. It is a constructor which gets called when you make an instance of the class and it is not necessary. But usually it our practice to write init method for setting default state of the object. If you are not willing to set any state of the object initially then you don’t need to write this method.


回答 15

# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()

回答 16

Python __init__及其作用self是什么?

怎么self办?这是什么意思?它是强制性的吗?

__init__方法做什么?为什么有必要?(等等。)

给出的示例不正确,因此让我基于它创建一个正确的示例:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

当我们创建对象的实例时,将__init__在对象创建后调用,以自定义对象。也就是说,当我们SomeObject'blah'下面的方法(可能是任何东西)进行调用时,它将__init__作为参数传递给函数blah

an_object = SomeObject('blah')

self参数是实例SomeObject,将被分配到an_object

稍后,我们可能要在此对象上调用方法:

an_object.method()

进行点分查找,即将an_object.method实例绑定到该函数的实例,并且该方法(如上所述)现在是“绑定”方法-这意味着我们无需将实例显式传递给方法调用。

方法调用获取实例是因为它绑定在点分查找上,并在调用时执行其编程要执行的任何代码。

隐式传递的self参数self由约定调用。我们可以使用其他任何合法的Python名称,但是如果将其更改为其他名称,您可能会被其他Python程序员感到羞耻和ed愧。

__init__是一种特殊的方法,在Python数据模型文档中进行了介绍。在创建实例后立即调用它(通常通过__new__-,尽管__new__不是必需的,除非您将不可变的数据类型作为子类)。

Python __init__ and self what do they do?

What does self do? What is it meant to be? Is it mandatory?

What does the __init__ method do? Why is it necessary? (etc.)

The example given is not correct, so let me create a correct example based on it:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

When we create an instance of the object, the __init__ is called to customize the object after it has been created. That is, when we call SomeObject with 'blah' below (which could be anything), it gets passed to the __init__ function as the argument, blah:

an_object = SomeObject('blah')

The self argument is the instance of SomeObject that will be assigned to an_object.

Later, we might want to call a method on this object:

an_object.method()

Doing the dotted lookup, that is, an_object.method, binds the instance to an instance of the function, and the method (as called above) is now a “bound” method – which means we do not need to explicitly pass the instance to the method call.

The method call gets the instance because it was bound on the dotted lookup, and when called, then executes whatever code it was programmed to perform.

The implicitly passed self argument is called self by convention. We could use any other legal Python name, but you will likely get tarred and feathered by other Python programmers if you change it to something else.

__init__ is a special method, documented in the Python datamodel documentation. It is called immediately after the instance is created (usually via __new__ – although __new__ is not required unless you are subclassing an immutable datatype).


回答 17

在这里,这家伙写得非常好而且很简单:https : //www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

阅读以上链接作为对此的参考:

self?那么,所有客户方法的自我参数又如何呢?它是什么?当然,这就是实例!换句话说,诸如提款之类的方法定义了从某个抽象客户帐户中提款的指令。调用jeff.withdraw(100.0)会将这些指令用于jeff实例。

因此,当我们说def withdraw(self,amount):时,我们的意思是,“这是您如何从Customer对象(我们称为self)和一个美元图形(我们称为amount)提取钱的方法。是被调用提现的Customer的实例,也不是我做类比。jeff.withdraw(100.0)只是Customer.withdraw(jeff,100.0)的简写,这是完全有效的(如果不经常出现)码。

init自我可能对其他方法有意义,但是init呢?当我们调用init时,我们正在创建一个对象,那么如何已经存在一个self?Python允许我们将self模式扩展到构造对象的时间,即使它并不完全适合。试想一下jeff = Customer(’Jeff Knupp’,1000.0)与调用jeff = Customer(jeff,’Jeff Knupp’,1000.0)相同;传入的jeff也成为结果。

这就是为什么当我们调用init时,我们通过说出self.name = name之类的东西来初始化对象。请记住,由于self是实例,所以这等效于说jeff.name = name,与jeff.name =’Jeff Knupp相同。同样,self.balance = balance与jeff.balance = 1000.0相同。在这两行之后,我们认为“客户”对象已“初始化”并可以使用。

小心你 __init__

经过初始化完成后,主叫方可以正确地假定对象就可以使用了。也就是说,在jeff = Customer(’Jeff Knupp’,1000.0)之后,我们可以开始对jeff进行入金和出金;jeff是一个完全初始化的对象。

Here, the guy has written pretty well and simple: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Read above link as a reference to this:

self? So what’s with that self parameter to all of the Customer methods? What is it? Why, it’s the instance, of course! Put another way, a method like withdraw defines the instructions for withdrawing money from some abstract customer’s account. Calling jeff.withdraw(100.0) puts those instructions to use on the jeff instance.

So when we say def withdraw(self, amount):, we’re saying, “here’s how you withdraw money from a Customer object (which we’ll call self) and a dollar figure (which we’ll call amount). self is the instance of the Customer that withdraw is being called on. That’s not me making analogies, either. jeff.withdraw(100.0) is just shorthand for Customer.withdraw(jeff, 100.0), which is perfectly valid (if not often seen) code.

init self may make sense for other methods, but what about init? When we call init, we’re in the process of creating an object, so how can there already be a self? Python allows us to extend the self pattern to when objects are constructed as well, even though it doesn’t exactly fit. Just imagine that jeff = Customer(‘Jeff Knupp’, 1000.0) is the same as calling jeff = Customer(jeff, ‘Jeff Knupp’, 1000.0); the jeff that’s passed in is also made the result.

This is why when we call init, we initialize objects by saying things like self.name = name. Remember, since self is the instance, this is equivalent to saying jeff.name = name, which is the same as jeff.name = ‘Jeff Knupp. Similarly, self.balance = balance is the same as jeff.balance = 1000.0. After these two lines, we consider the Customer object “initialized” and ready for use.

Be careful what you __init__

After init has finished, the caller can rightly assume that the object is ready to use. That is, after jeff = Customer(‘Jeff Knupp’, 1000.0), we can start making deposit and withdraw calls on jeff; jeff is a fully-initialized object.


删除字符串中的所有空格

问题:删除字符串中的所有空格

我想消除字符串两端和单词之间的所有空白。

我有这个Python代码:

def my_handle(self):
    sentence = ' hello  apple  '
    sentence.strip()

但这仅消除了字符串两侧的空白。如何删除所有空格?

I want to eliminate all the whitespace from a string, on both ends, and in between words.

I have this Python code:

def my_handle(self):
    sentence = ' hello  apple  '
    sentence.strip()

But that only eliminates the whitespace on both sides of the string. How do I remove all whitespace?


回答 0

如果要删除开头和结尾的空格,请使用str.strip()

sentence = ' hello  apple'
sentence.strip()
>>> 'hello  apple'

如果要删除所有空格字符,请使用str.replace()

(注意,这只会删除“常规” ASCII空格字符,' ' U+0020而不会删除任何其他空白

sentence = ' hello  apple'
sentence.replace(" ", "")
>>> 'helloapple'

如果要删除重复的空格,请使用str.split()

sentence = ' hello  apple'
" ".join(sentence.split())
>>> 'hello apple'

If you want to remove leading and ending spaces, use str.strip():

sentence = ' hello  apple'
sentence.strip()
>>> 'hello  apple'

If you want to remove all space characters, use str.replace():

(NB this only removes the “normal” ASCII space character ' ' U+0020 but not any other whitespace)

sentence = ' hello  apple'
sentence.replace(" ", "")
>>> 'helloapple'

If you want to remove duplicated spaces, use str.split():

sentence = ' hello  apple'
" ".join(sentence.split())
>>> 'hello apple'

回答 1

删除空格,请使用str.replace

sentence = sentence.replace(' ', '')

要删除所有空白字符(空格,制表符,换行符等),可以使用splitthen join

sentence = ''.join(sentence.split())

或正则表达式:

import re
pattern = re.compile(r'\s+')
sentence = re.sub(pattern, '', sentence)

如果只想从头到尾删除空格,则可以使用strip

sentence = sentence.strip()

您还可以lstrip用于仅从字符串的开头rstrip删除空格,并从字符串的结尾删除空格。

To remove only spaces use str.replace:

sentence = sentence.replace(' ', '')

To remove all whitespace characters (space, tab, newline, and so on) you can use split then join:

sentence = ''.join(sentence.split())

or a regular expression:

import re
pattern = re.compile(r'\s+')
sentence = re.sub(pattern, '', sentence)

If you want to only remove whitespace from the beginning and end you can use strip:

sentence = sentence.strip()

You can also use lstrip to remove whitespace only from the beginning of the string, and rstrip to remove whitespace from the end of the string.


回答 2

另一种选择是使用正则表达式并匹配这些奇怪的空白字符。这里有些例子:

删除字符串中的所有空格,即使单词之间也是如此:

import re
sentence = re.sub(r"\s+", "", sentence, flags=re.UNICODE)

在字符串的开头删除空格:

import re
sentence = re.sub(r"^\s+", "", sentence, flags=re.UNICODE)

删除字符串末尾的空格:

import re
sentence = re.sub(r"\s+$", "", sentence, flags=re.UNICODE)

删除字符串的开始和结尾处的空格:

import re
sentence = re.sub("^\s+|\s+$", "", sentence, flags=re.UNICODE)

删除仅重复的空格:

import re
sentence = " ".join(re.split("\s+", sentence, flags=re.UNICODE))

(所有示例均可在Python 2和Python 3中使用)

An alternative is to use regular expressions and match these strange white-space characters too. Here are some examples:

Remove ALL spaces in a string, even between words:

import re
sentence = re.sub(r"\s+", "", sentence, flags=re.UNICODE)

Remove spaces in the BEGINNING of a string:

import re
sentence = re.sub(r"^\s+", "", sentence, flags=re.UNICODE)

Remove spaces in the END of a string:

import re
sentence = re.sub(r"\s+$", "", sentence, flags=re.UNICODE)

Remove spaces both in the BEGINNING and in the END of a string:

import re
sentence = re.sub("^\s+|\s+$", "", sentence, flags=re.UNICODE)

Remove ONLY DUPLICATE spaces:

import re
sentence = " ".join(re.split("\s+", sentence, flags=re.UNICODE))

(All examples work in both Python 2 and Python 3)


回答 3

空格包括空格,制表符和CRLF。因此,我们可以使用的一种优雅的单线字符串函数是str.translate

Python 3

' hello  apple'..translate(str.maketrans('', '', ' \n\t\r'))

或者,如果您想彻底了解:

import string
' hello  apple'..translate(str.maketrans('', '', string.whitespace))

Python 2

' hello  apple'.translate(None, ' \n\t\r')

或者,如果您想彻底了解:

import string
' hello  apple'.translate(None, string.whitespace)

Whitespace includes space, tabs, and CRLF. So an elegant and one-liner string function we can use is str.translate:

Python 3

' hello  apple'..translate(str.maketrans('', '', ' \n\t\r'))

OR if you want to be thorough:

import string
' hello  apple'..translate(str.maketrans('', '', string.whitespace))

Python 2

' hello  apple'.translate(None, ' \n\t\r')

OR if you want to be thorough:

import string
' hello  apple'.translate(None, string.whitespace)

回答 4

要从开头和结尾删除空格,请使用strip

>> "  foo bar   ".strip()
"foo bar"

For removing whitespace from beginning and end, use strip.

>> "  foo bar   ".strip()
"foo bar"

回答 5

' hello  \n\tapple'.translate({ord(c):None for c in ' \n\t\r'})

MaK已经指出了上面的“翻译”方法。而且此变体适用于Python 3(请参阅此Q&A)。

' hello  \n\tapple'.translate({ord(c):None for c in ' \n\t\r'})

MaK already pointed out the “translate” method above. And this variation works with Python 3 (see this Q&A).


回答 6

小心:

strip 执行rstrip和lstrip(删除前导和尾随空格,制表符,返回和换页,但不会在字符串中间删除它们)。

如果仅替换空格和制表符,则最终可能会出现隐藏的CRLF,这些CRLF似乎与您要查找的内容匹配,但并不相同。

Be careful:

strip does a rstrip and lstrip (removes leading and trailing spaces, tabs, returns and form feeds, but it does not remove them in the middle of the string).

If you only replace spaces and tabs you can end up with hidden CRLFs that appear to match what you are looking for, but are not the same.


回答 7

import re    
sentence = ' hello  apple'
re.sub(' ','',sentence) #helloworld (remove all spaces)
re.sub('  ',' ',sentence) #hello world (remove double spaces)
import re    
sentence = ' hello  apple'
re.sub(' ','',sentence) #helloworld (remove all spaces)
re.sub('  ',' ',sentence) #hello world (remove double spaces)

回答 8

此外,strip具有一些变化:

删除字符串的BEGINNING和END中的空格:

sentence= sentence.strip()

在字符串的开头删除空格:

sentence = sentence.lstrip()

删除字符串末尾的空格:

sentence= sentence.rstrip()

这三个字符串函数strip lstriprstrip都可以使用要删除的字符串参数,默认为全空格。当您处理某些特殊内容时,这可能会很有帮助,例如,您只能删除空格,而不能删除换行符:

" 1. Step 1\n".strip(" ")

或者,您可以在读取字符串列表时删除多余的逗号:

"1,2,3,".strip(",")

In addition, strip has some variations:

Remove spaces in the BEGINNING and END of a string:

sentence= sentence.strip()

Remove spaces in the BEGINNING of a string:

sentence = sentence.lstrip()

Remove spaces in the END of a string:

sentence= sentence.rstrip()

All three string functions strip lstrip, and rstrip can take parameters of the string to strip, with the default being all white space. This can be helpful when you are working with something particular, for example, you could remove only spaces but not newlines:

" 1. Step 1\n".strip(" ")

Or you could remove extra commas when reading in a string list:

"1,2,3,".strip(",")

回答 9

从字符串的两端和单词之间消除所有空格。

>>> import re
>>> re.sub("\s+", # one or more repetition of whitespace
    '', # replace with empty string (->remove)
    ''' hello
...    apple
... ''')
'helloapple'

Python文档:

eliminate all the whitespace from a string, on both ends, and in between words.

>>> import re
>>> re.sub("\s+", # one or more repetition of whitespace
    '', # replace with empty string (->remove)
    ''' hello
...    apple
... ''')
'helloapple'

Python docs:


python setup.py卸载

问题:python setup.py卸载

我已经使用安装了python软件包python setup.py install

如何卸载?

I have installed a python package with python setup.py install.

How do I uninstall it?


回答 0

注意:避免python setup.py install使用pip install .

您需要手动删除所有文件,还需要撤消安装过程中手动执行的任何其他操作。

如果您不知道所有文件的列表,则可以使用--record选件重新安装它,然后查看生成的列表。

要记录已安装文件的列表,可以使用:

python setup.py install --record files.txt

想要卸载后,可以使用xargs进行删除:

xargs rm -rf < files.txt

或者,如果您正在运行Windows,请使用Powershell:

Get-Content files.txt | ForEach-Object {Remove-Item $_ -Recurse -Force}

然后也删除包含的目录,例如/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/my_module-0.1.egg/on macOS。它没有文件,但是Python仍将导入一个空模块:

>>> import my_module
>>> my_module.__file__
None

删除后,Python将显示:

>>> import my_module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'my_module'

Note: Avoid using python setup.py install use pip install .

You need to remove all files manually, and also undo any other stuff that installation did manually.

If you don’t know the list of all files, you can reinstall it with the --record option, and take a look at the list this produces.

To record a list of installed files, you can use:

python setup.py install --record files.txt

Once you want to uninstall you can use xargs to do the removal:

xargs rm -rf < files.txt

Or if you’re running Windows, use Powershell:

Get-Content files.txt | ForEach-Object {Remove-Item $_ -Recurse -Force}

Then delete also the containing directory, e.g. /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/my_module-0.1.egg/ on macOS. It has no files, but Python will still import an empty module:

>>> import my_module
>>> my_module.__file__
None

Once deleted, Python shows:

>>> import my_module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'my_module'

回答 1

对我来说,以下主要工作方式:

已安装点子,例如:

$ easy_install pip

从pip的角度检查已安装的软件包的名称:

$ pip freeze

这将列出您已经安装(并且被pip检测到)的所有软件包的名称。该名称可能会很长,然后仅使用和之后显示的程序包的名称#egg=。在大多数情况下,您也可以忽略版本部分(无论是后面的==还是-)。

然后卸载该软件包:

$ pip uninstall package.name.you.have.found

如果它要求您确认删除软件包,那么您很幸运,它将被删除。

pip应检测所有由pip安装的软件包。它还应检测通过easy_install或setup.py安装的大多数软件包,但这在极少数情况下可能会失败。

这是来自本地测试的真实示例,带有ttr.rdstmc在Windows上命名的软件包。

$ pip freeze |grep ttr
ttr.aws.s3==0.1.1dev
ttr.aws.utils.s3==0.3.0
ttr.utcutils==0.1.1dev

$ python setup.py develop
.....
.....
Finished processing dependencies for ttr.rdstmc==0.0.1dev

$ pip freeze |grep ttr
ttr.aws.s3==0.1.1dev
ttr.aws.utils.s3==0.3.0
-e hg+https://vlcinsky@bitbucket.org/vlcinsky/ttr.rdstmc@d61a9922920c508862602f7f39e496f7b99315f0#egg=ttr.rdstmc-dev
ttr.utcutils==0.1.1dev

$ pip uninstall ttr.rdstmc
Uninstalling ttr.rdstmc:
  c:\python27\lib\site-packages\ttr.rdstmc.egg-link
Proceed (y/n)? y
  Successfully uninstalled ttr.rdstmc

$ pip freeze |grep ttr
ttr.aws.s3==0.1.1dev
ttr.aws.utils.s3==0.3.0
ttr.utcutils==0.1.1dev

编辑2015-05-20

上面写的所有内容仍然适用,无论如何,现在有一些小的修改。

在python 2.7.9和python 3.4中安装pip

最新的python版本附带了一个软件包ensurepip,即使离线也可以安装pip:

$ python -m surepip-升级

在某些系统(例如Debian Jessie)上,此功能不可用(以防止破坏系统python安装)。

使用grepfind

上面的示例假定您已grep安装。我(当时我的计算机上装有MS Windows)安装了一套Linux实用程序(包括grep)。或者,使用本机MS Windows find或简单地忽略该过滤,并在更长的检测到的python软件包列表中找到名称。

For me, the following mostly works:

have pip installed, e.g.:

$ easy_install pip

Check, how is your installed package named from pip point of view:

$ pip freeze

This shall list names of all packages, you have installed (and which were detected by pip). The name can be sometime long, then use just the name of the package being shown at the and after #egg=. You can also in most cases ignore the version part (whatever follows == or -).

Then uninstall the package:

$ pip uninstall package.name.you.have.found

If it asks for confirmation about removing the package, then you are lucky guy and it will be removed.

pip shall detect all packages, which were installed by pip. It shall also detect most of the packages installed via easy_install or setup.py, but this may in some rare cases fail.

Here is real sample from my local test with package named ttr.rdstmc on MS Windows.

$ pip freeze |grep ttr
ttr.aws.s3==0.1.1dev
ttr.aws.utils.s3==0.3.0
ttr.utcutils==0.1.1dev

$ python setup.py develop
.....
.....
Finished processing dependencies for ttr.rdstmc==0.0.1dev

$ pip freeze |grep ttr
ttr.aws.s3==0.1.1dev
ttr.aws.utils.s3==0.3.0
-e hg+https://vlcinsky@bitbucket.org/vlcinsky/ttr.rdstmc@d61a9922920c508862602f7f39e496f7b99315f0#egg=ttr.rdstmc-dev
ttr.utcutils==0.1.1dev

$ pip uninstall ttr.rdstmc
Uninstalling ttr.rdstmc:
  c:\python27\lib\site-packages\ttr.rdstmc.egg-link
Proceed (y/n)? y
  Successfully uninstalled ttr.rdstmc

$ pip freeze |grep ttr
ttr.aws.s3==0.1.1dev
ttr.aws.utils.s3==0.3.0
ttr.utcutils==0.1.1dev

Edit 2015-05-20

All what is written above still applies, anyway, there are small modifications available now.

Install pip in python 2.7.9 and python 3.4

Recent python versions come with a package ensurepip allowing to install pip even when being offline:

$ python -m ensurepip –upgrade

On some systems (like Debian Jessie) this is not available (to prevent breaking system python installation).

Using grep or find

Examples above assume, you have grep installed. I had (at the time I had MS Windows on my machine) installed set of linux utilities (incl. grep). Alternatively, use native MS Windows find or simply ignore that filtering and find the name in a bit longer list of detected python packages.


回答 2

第一个答案有问题:

  • 在Mac上无法使用。
  • 如果安装的文件包含空格或其他特殊字符,该xargs命令将失败,并删除与各个单词匹配的所有文件/目录。
  • -rrm -rf是不必要的,在最坏的情况可能会删除你不想要的东西。

相反,对于类Unix:

sudo python setup.py install --record files.txt
# inspect files.txt to make sure it looks ok. Then:
tr '\n' '\0' < files.txt | xargs -0 sudo rm -f --

对于Windows:

python setup.py bdist_wininst
dist/foo-1.0.win32.exe

卸载setup.py安装还有一些无法解决的问题,在典型情况下不会打扰您。有关更完整的答案,请参见以下Wiki页面:

https://ofswiki.org/wiki/Uninstalling_setup.py_install

The #1 answer has problems:

  • Won’t work on mac.
  • If a file is installed which includes spaces or other special characters, the xargs command will fail, and delete any files/directories which matched the individual words.
  • the -r in rm -rf is unnecessary and at worst could delete things you don’t want to.

Instead, for unix-like:

sudo python setup.py install --record files.txt
# inspect files.txt to make sure it looks ok. Then:
tr '\n' '\0' < files.txt | xargs -0 sudo rm -f --

And for windows:

python setup.py bdist_wininst
dist/foo-1.0.win32.exe

There are also unsolvable problems with uninstalling setup.py install which won’t bother you in a typical case. For a more complete answer, see this wiki page:

https://ofswiki.org/wiki/Uninstalling_setup.py_install


回答 3

首先记录您已安装的文件。即使您先前已经运行过,也可以重复此命令setup.py install

python setup.py install --record files.txt

要卸载时,您可以:

sudo rm $(cat files.txt)

之所以可行,是因为rm命令使用空格分隔的文件列表来删除,并且您的安装记录就是这样的列表。

First record the files you have installed. You can repeat this command, even if you have previously run setup.py install:

python setup.py install --record files.txt

When you want to uninstall you can just:

sudo rm $(cat files.txt)

This works because the rm command takes a whitespace-seperated list of files to delete and your installation record is just such a list.


回答 4

现在,python让您可以选择在安装pip过程中进行安装(我在Windows上,至少python在Windows上可以!)。考虑到您已选择pip在安装python时进行安装(实际上是默认设置,因此不必选择),pip已经为您安装了。然后,pip在命令提示符下键入,您应该会看到一个帮助。您可以在此处找到必要的使用说明。例如,pip list显示已安装软件包的列表。您可以使用

pip uninstall package_name

卸载不再需要的任何软件包。在此处阅读更多信息(pip文档)

Now python gives you the choice to install pip during the installation (I am on Windows, and at least python does so for Windows!). Considering you had chosen to install pip during installation of python (you don’t actually have to choose because it is default), pip is already installed for you. Then, type in pip in command prompt, you should see a help come up. You can find necessary usage instructions there. E.g. pip list shows you the list of installed packages. You can use

pip uninstall package_name

to uninstall any package that you don’t want anymore. Read more here (pip documentation).


回答 5

懒惰的方式:只需从Windows安装菜单(如果使用Windows)或从rpm命令卸载,前提是您在创建分发程序包后首先重新安装它。

例如,

python setup.py bdist_wininst
dist/foo-1.0.win32.exe

(“ foo”当然是示例)。

The lazy way: simply uninstall from the Windows installation menu (if you’re using Windows), or from the rpm command, provided you first re-install it after creating a distribution package.

For example,

python setup.py bdist_wininst
dist/foo-1.0.win32.exe

(“foo” being an example of course).


回答 6

转到python软件包目录并删除.egg文件,例如:在python 2.5(ubuntu)中:/usr/lib/python2.5/site-packages/

在python 2.6(ubuntu)中:/usr/local/lib/python2.6/dist-packages/

Go to your python package directory and remove your .egg file, e.g.: In python 2.5(ubuntu): /usr/lib/python2.5/site-packages/

In python 2.6(ubuntu): /usr/local/lib/python2.6/dist-packages/


回答 7

不能完全回答问题,但每天都能对我有所帮助:

安装您的软件包

pip install .

这会将包装放入$HOME/.local。卸载

pip uninstall <package_name>

Not exactly answering the question, but something that helps me every day:

Install your packages with

pip install .

This puts the package in $HOME/.local. Uninstall with

pip uninstall <package_name>

回答 8

可能您可以这样做:

1)获取python版本-

[linux machine]# python
Python 2.4.3 (#1, Jun 18 2012, 14:38:55) 

->上面的命令为您提供了当前的python版本2.4.3

2)获取python的安装目录-

[linux machine]# whereis python
python: /usr/bin/python /usr/bin/python2.4 /usr/lib/python2.4 /usr/local/bin/python2.5 /usr/include/python2.4 /usr/share/man/man1/python.1.gz

->从上面的命令中,您可以获得安装目录-/ usr/lib/python2.4/sitepackages

3)从这里您可以删除软件包和python egg文件

[linux machine]# cd /usr/lib/python2.4/site-packages
[linux machine]# rm -rf paramiko-1.12.0-py2.4.egg paramiko-1.7.7.1-py2.4.egg paramiko-1.9.0-py2.4.egg

这对我有用。而且我能够卸载困扰我的软件包:)

Probably you can do this as an alternative :-

1) Get the python version –

[linux machine]# python
Python 2.4.3 (#1, Jun 18 2012, 14:38:55) 

-> The above command gives you the current python Version which is 2.4.3

2) Get the installation directory of python –

[linux machine]# whereis python
python: /usr/bin/python /usr/bin/python2.4 /usr/lib/python2.4 /usr/local/bin/python2.5 /usr/include/python2.4 /usr/share/man/man1/python.1.gz

-> From above command you can get the installation directory which is – /usr/lib/python2.4/site-packages

3) From here you can remove the packages and python egg files

[linux machine]# cd /usr/lib/python2.4/site-packages
[linux machine]# rm -rf paramiko-1.12.0-py2.4.egg paramiko-1.7.7.1-py2.4.egg paramiko-1.9.0-py2.4.egg

This worked for me.. And i was able to uninstall package which was troubling me :)


回答 9

我认为您可以打开setup.py,找到软件包名称,然后要求pip卸载它。

假设名称在“ METADATA”变量中可用:

pip uninstall $(python -c "from setup import METADATA; print METADATA['name']")

I think you can open the setup.py, locate the package name, and then ask pip to uninstall it.

Assuming the name is available in a ‘METADATA’ variable:

pip uninstall $(python -c "from setup import METADATA; print METADATA['name']")

回答 10

扩展一下Martin所说的内容,记录安装输出和一些bash脚本就可以很好地解决问题。这是我的工作

for i in $(less install.record);
sudo rm $i;
done;

和presto。已卸载。

Extending on what Martin said, recording the install output and a little bash scripting does the trick quite nicely. Here’s what I do…

for i in $(less install.record);
sudo rm $i;
done;

And presto. Uninstalled.


回答 11

如果在重新安装软件包后仍有一些文件应删除,请确保该文件夹build也已删除。因此,假设这pkg是您要删除的软件包:

rm -r $(python3 -c "import pkg; print(pkg.__path__[0] + '*' )") 
rm -rf build

以上为python3计算并删除了软件包及其* .egg-info文件

If you still have files that are supposed to be deleted after re-installing a package, make sure the folder build is also deleted. Therefore, assuming that pkg is the package you want to delete:

rm -r $(python3 -c "import pkg; print(pkg.__path__[0] + '*' )") 
rm -rf build

Obove work out for python3 and delete the package and its *.egg-info file


回答 12

{virtualenv}/lib/python2.7/site-packages/(如果未使用virtualenv,则为{system_dir}/lib/python2.7/dist-packages/

  • 删除鸡蛋文件(例如distribute-0.6.34-py2.7.egg
  • 如果文件中有任何内容easy-install.pth,请删除相应的行(它应该是源目录或egg文件的路径)。

At {virtualenv}/lib/python2.7/site-packages/ (if not using virtualenv then {system_dir}/lib/python2.7/dist-packages/)

  • Remove the egg file (e.g. distribute-0.6.34-py2.7.egg)
  • If there is any from file easy-install.pth, remove the corresponding line (it should be a path to the source directory or of an egg file).

回答 13

我过去曾经在全局环境中偶然运行过“ python setup.py install”,并且卸载时遇到很多困难。这些解决方案没有帮助。“ pip卸载”不适用于“无法卸载’splunk-appinspect’。找不到要卸载的文件。” “ sudo pip卸载”不起作用“无法卸载要求splunk-appinspect,未安装”。我尝试卸载pip,删除pip缓存,在硬盘上搜索该软件包等,…

“ pip show”最终将我引向解决方案,“ Location:”指向目录,并且重命名该目录导致打包的内容从pip列表中删除。我重命名了目录,但它没有重新出现在pip的列表中,现在我可以在virtualenv中重新安装我的软件包了。

I had run “python setup.py install” at some point in the past accidentally in my global environment, and had much difficulty uninstalling. These solutions didn’t help. “pip uninstall ” didn’t work with “Can’t uninstall ‘splunk-appinspect’. No files were found to uninstall.” “sudo pip uninstall ” didn’t work “Cannot uninstall requirement splunk-appinspect, not installed”. I tried uninstalling pip, deleting the pip cache, searching my hard drive for the package, etc…

“pip show ” eventually led me to the solution, the “Location:” was pointing to a directory, and renaming that directory caused the packaged to be removed from pip’s list. I renamed the directory back, and it didn’t reappear in pip’s list, and now I can reinstall my package in a virtualenv.


回答 14

python setup.py install在PyCharm中运行了一次,它将所有软件包安装到conda基本环境中。以后,当我要删除所有这些程序包时,将pip uninstall无法正常工作。我不得不从/anaconda3/lib/python3.7/site-packages中手动删除它们:(

因此,我看不出他们为什么使用setup.py而不是编写requirements.txt文件的原因。需求文件可用于在虚拟环境中安装软件包,并且不会与系统python软件包混淆。

I had run python setup.py install once in my PyCharm, it installs all the packages into my conda base environment. Later when I want to remove all these packages, pip uninstall does not work. I had to delete them from /anaconda3/lib/python3.7/site-packages manually :(

So I don’t see the reason why they use setup.py instead of writing requirements.txt file. The requirement file can be used to install packages in virtual environment and won’t mess with system python packages.


回答 15

最好使用bash读取命令来删除相关文件,如下所示:

sudo python setup.py install --record files.txt
sudo bash -c "cat files.txt | xargs rm -rf"

It might be better to remove related files by using bash to read commands, like the following:

sudo python setup.py install --record files.txt
sudo bash -c "cat files.txt | xargs rm -rf"

在virtualenv中使用Python 3

问题:在virtualenv中使用Python 3

使用virtualenv,我使用默认版本的Python(2.7)运行项目。在一个项目中,我需要使用Python 3.4。

我曾经brew install python3将其安装在Mac上。现在,如何创建使用新版本的virtualenv?

例如sudo virtualenv envPython3

如果我尝试:

virtualenv -p python3 test

我得到:

Running virtualenv with interpreter /usr/local/bin/python3
Using base prefix '/usr/local/Cellar/python3/3.4.0_1/Frameworks/Python.framework/Versions/3.4'
New python executable in test/bin/python3.4
Also creating executable in test/bin/python
Failed to import the site module
Traceback (most recent call last):
  File "/Users/user/Documents/workspace/test/test/bin/../lib/python3.4/site.py", line 67, in <module>
    import os
  File "/Users/user/Documents/workspace/test/test/bin/../lib/python3.4/os.py", line 634, in <module>
    from _collections_abc import MutableMapping
ImportError: No module named '_collections_abc'
ERROR: The executable test/bin/python3.4 is not functioning
ERROR: It thinks sys.prefix is '/Users/user/Documents/workspace/test' (should be '/Users/user/Documents/workspace/test/test')
ERROR: virtualenv is not compatible with this system or executable

Using virtualenv, I run my projects with the default version of Python (2.7). On one project, I need to use Python 3.4.

I used brew install python3 to install it on my Mac. Now, how do I create a virtualenv that uses the new version?

e.g. sudo virtualenv envPython3

If I try:

virtualenv -p python3 test

I get:

Running virtualenv with interpreter /usr/local/bin/python3
Using base prefix '/usr/local/Cellar/python3/3.4.0_1/Frameworks/Python.framework/Versions/3.4'
New python executable in test/bin/python3.4
Also creating executable in test/bin/python
Failed to import the site module
Traceback (most recent call last):
  File "/Users/user/Documents/workspace/test/test/bin/../lib/python3.4/site.py", line 67, in <module>
    import os
  File "/Users/user/Documents/workspace/test/test/bin/../lib/python3.4/os.py", line 634, in <module>
    from _collections_abc import MutableMapping
ImportError: No module named '_collections_abc'
ERROR: The executable test/bin/python3.4 is not functioning
ERROR: It thinks sys.prefix is '/Users/user/Documents/workspace/test' (should be '/Users/user/Documents/workspace/test/test')
ERROR: virtualenv is not compatible with this system or executable

回答 0

只需运行

virtualenv -p python3 envname

OP编辑后更新:

有没有在OP的版本virtualenv中的一个bug,如所描述这里。该问题已通过运行解决:

pip install --upgrade virtualenv

simply run

virtualenv -p python3 envname

Update after OP’s edit:

There was a bug in the OP’s version of virtualenv, as described here. The problem was fixed by running:

pip install --upgrade virtualenv

回答 1

Python 3具有对虚拟环境venv的内置支持。最好改用它。参考文档:

通过执行pyvenv脚本来创建虚拟环境:

pyvenv /path/to/new/virtual/environment

适用于Python 3.6及更高版本的更新:

由于pawciobiel正确注释了pyvenv因此从Python 3.6开始不推荐使用,新方法是:

python3 -m venv /path/to/new/virtual/environment

Python 3 has a built-in support for virtual environments – venv. It might be better to use that instead. Referring to the docs:

Creation of virtual environments is done by executing the pyvenv script:

pyvenv /path/to/new/virtual/environment

Update for Python 3.6 and newer:

As pawciobiel correctly comments, pyvenv is deprecated as of Python 3.6 and the new way is:

python3 -m venv /path/to/new/virtual/environment

回答 2

我尝试过pyenv,它对于切换python版本(全局,文件夹或virtualenv中的本地)非常方便:

brew install pyenv

然后安装所需的Python版本:

pyenv install 3.5.0

并只需创建virtualenv并包含所需解释器版本的路径即可:

virtualenv -p /Users/johnny/.pyenv/versions/3.5.0/bin/python3.5 myenv

就是这样,检查版本:

. ./myenv/bin/activate && python -V

也有pyenv的插件pyenv-virtualenv,但是它对我不起作用。

I’v tried pyenv and it’s very handy for switching python versions (global, local in folder or in the virtualenv):

brew install pyenv

then install Python version you want:

pyenv install 3.5.0

and simply create virtualenv with path to needed interpreter version:

virtualenv -p /Users/johnny/.pyenv/versions/3.5.0/bin/python3.5 myenv

That’s it, check the version:

. ./myenv/bin/activate && python -V

There are also plugin for pyenv pyenv-virtualenv but it didn’t work for me somehow.


回答 3

安装先决条件。

sudo apt-get install python3 python3-pip virtualenvwrapper

创建一个基于Python3的虚拟环境。(可选)启用--system-site-packages标志。

mkvirtualenv -p /usr/bin/python3 <venv-name>

设置到虚拟环境中。

workon <venv-name>

使用pip程序包管理器安装其他要求。

pip install -r requirements.txt
pip install <package_name>

当同时处理多个python项目时,通常建议安装pdbpp全局通用包,然后在virtualenvs中重用它们。

除了消耗最少的磁盘空间和网络带宽外,使用此技术还节省了很多时间来获取软件包和安装软件包。

sudo -H pip3 -v install pdbpp
mkvirtualenv -p $(which python3) --system-site-packages <venv-name>

Django特定说明

如果有很多系统范围的python软件包,那么建议不要使用--system-site-packagesflag,尤其是在开发过程中,因为我注意到它会大大降低Django的启动速度。我认为Django环境初始化是手动扫描并从系统路径附加所有站点包,这可能是原因。甚至python manage.py shell变得很慢。

话虽如此,实验哪个选项更好。跳过--system-site-packagesDjango项目的标志可能是安全的。

Install prerequisites.

sudo apt-get install python3 python3-pip virtualenvwrapper

Create a Python3 based virtual environment. Optionally enable --system-site-packages flag.

mkvirtualenv -p /usr/bin/python3 <venv-name>

Set into the virtual environment.

workon <venv-name>

Install other requirements using pip package manager.

pip install -r requirements.txt
pip install <package_name>

When working on multiple python projects simultaneously it is usually recommended to install common packages like pdbpp globally and then reuse them in virtualenvs.

Using this technique saves a lot of time spent on fetching packages and installing them, apart from consuming minimal disk space and network bandwidth.

sudo -H pip3 -v install pdbpp
mkvirtualenv -p $(which python3) --system-site-packages <venv-name>

Django specific instructions

If there are a lot of system wide python packages then it is recommended to not use --system-site-packages flag especially during development since I have noticed that it slows down Django startup a lot. I presume Django environment initialisation is manually scanning and appending all site packages from the system path which might be the reason. Even python manage.py shell becomes very slow.

Having said that experiment which option works better. Might be safe to just skip --system-site-packages flag for Django projects.


回答 4

virtualenv --python=/usr/bin/python3 <name of env>

为我工作。

virtualenv --python=/usr/bin/python3 <name of env>

worked for me.


回答 5

您可以在创建环境时指定特定的Python版本
virtualenv.py中提到

virtualenv --python=python3.5 envname

在某些情况下,这必须是可执行文件的完整路径:

virtualenv --python=/Users/username/.pyenv/versions/3.6.0/bin/python3.6 envname

如何-p工作

parser.add_option(
    '-p', '--python',
    dest='python',
    metavar='PYTHON_EXE',
    help='The Python interpreter to use, e.g., --python=python3.5 will use the python3.5 '
    'interpreter to create the new environment.  The default is the interpreter that '
    'virtualenv was installed with (%s)' % sys.executable)

You can specify specific Version of Python while creating environment.
It’s mentioned in virtualenv.py

virtualenv --python=python3.5 envname

In some cases this has to be the full path to the executable:

virtualenv --python=/Users/username/.pyenv/versions/3.6.0/bin/python3.6 envname

How -p works

parser.add_option(
    '-p', '--python',
    dest='python',
    metavar='PYTHON_EXE',
    help='The Python interpreter to use, e.g., --python=python3.5 will use the python3.5 '
    'interpreter to create the new environment.  The default is the interpreter that '
    'virtualenv was installed with (%s)' % sys.executable)

回答 6

我有同样的ERROR信息。在我的情况下,tbrisker的解决方案不起作用。相反,这解决了问题:

$ python3 -m venv .env

I had the same ERROR message. tbrisker’s solution did not work in my case. Instead this solved the issue:

$ python3 -m venv .env

回答 7

这就是您所需要的,以便在python / python3中运行虚拟环境

首先,如果virtualenv未安装,请运行

pip3 install virtualenv 

现在运行:

virtualenv -p python3 <env name> 

有时,cmd virtualenv失败,请使用以下命令:

python3 -m virtualenv <env_name>  # you can specify full path instead <env_name> to install the file in a different location other than the current location

现在激活虚拟环境:

source <env_name>/bin/activate

要么:

source `pwd`/<env_name>/bin/activate

现在运行

which python

您应该看到目录和<env_name>/bin/python后缀的完整路径

要退出virtualenv,请运行:

deactivate 

This is all you need, in order to run a virtual environment in python / python3

First if virtualenv not installed, run

pip3 install virtualenv 

Now Run:

virtualenv -p python3 <env name> 

Sometime the cmd virtualenv fails, if so use this:

python3 -m virtualenv <env_name>  # you can specify full path instead <env_name> to install the file in a different location other than the current location

Now activate the virtual env:

source <env_name>/bin/activate

Or:

source `pwd`/<env_name>/bin/activate

Now run

which python

You should see the full path to your dir and <env_name>/bin/python suffix

To exit the virtualenv, run:

deactivate 

回答 8

Python现在带有自己的虚拟环境实现,名称为“ venv”。我建议使用它,而不是virtualenv。

引用venv-docs

自3.6版起不推荐使用:pyvenv是为Python 3.3和3.4创建虚拟环境的推荐工具,在Python 3.6中不推荐使用。

在版本3.5中进行了更改:现在建议使用venv创建虚拟环境。

对于Windows,要在某些项目上启动venv,请打开cmd:

python -m venv "c:\path\to\myenv"

(如果目录路径包含空格,建议在目录路径周围使用双引号。例如:“ C:/ My Dox / Spaced Directory / Something”)

设置venv后,您将在项目目录中看到一些新文件夹。其中之一就是“脚本”。

要激活或调用venv,您需要:

C:\> <venv>\Scripts\activate.bat

您可以通过在Shell中键入“ deactivate”来停用虚拟环境。这样,您现在就可以安装特定于项目的库,该库位于文件夹“ Lib”下。

===============================编辑1 ================ ====================下面将要讨论的场景不是最初要求的,只是在有人将vscode与python扩展一起使用的情况下添加此场景

如果您使用vs代码及其python扩展名,您的pylint可能会遇到问题,该问题指向全局安装。在这种情况下,pylint将无法查看虚拟环境中安装的模块,因此在导入时将显示错误。

是克服此问题的简单方法。

cd Workspace\Scripts
.\Activate.ps1
code .

我们基本上是先激活环境,然后再调用vs代码,以便pylint在环境中启动并可以看到所有本地包。

Python now comes with its own implementation of virtual environment, by the name of “venv”. I would suggest using that, instead of virtualenv.

Quoting from venv – docs,

Deprecated since version 3.6: pyvenv was the recommended tool for creating virtual environments for Python 3.3 and 3.4, and is deprecated in Python 3.6.

Changed in version 3.5: The use of venv is now recommended for creating virtual environments.

For windows, to initiate venv on some project, open cmd:

python -m venv "c:\path\to\myenv"

(Would suggest using double quote around directory path if it contains any spaces. Ex: “C:/My Dox/Spaced Directory/Something”)

Once venv is set up, you will see some new folders inside your project directory. One of them would be “Scripts”.

To activate or invoke venv you need:

C:\> <venv>\Scripts\activate.bat

You can deactivate a virtual environment by typing “deactivate” in your shell. With this, you are now ready to install your project specific libraries, which will reside under the folder “Lib”.

================================ Edit 1 ==================================== The scenario which will be discussed below is not what originally asked, just adding this in case someone use vscode with python extension

In case, you use vs code with its python extension, you might face an issue with its pylint which points to the global installation. In this case, pylint won’t be able to see the modules that are installed in your virtual environment and hence will show errors while importing.

Here is a simple method to get past this.

cd Workspace\Scripts
.\Activate.ps1
code .

We are basically activating the environment first and then invoking vs-code so that pylint starts within the environment and can see all local packages.


回答 9

除了其他答案,我建议检查您正在执行哪个virtualenv实例:

which virtualenv

如果在/ usr / local / bin中出现问题,则可能甚至可能安装了virtualenv(可能使用easy_tools或pip实例)而没有使用系统的程序包管理器(在OP中为棕色)。这是我的问题。

多年前-当我更加无知的时候-我安装了virtualenv,它掩盖了我系统的软件包提供的virtualenv。

删除了这个破旧的virtualenv之后,我的问题就消失了。

In addition to the other answers, I recommend checking what instance of virtualenv you are executing:

which virtualenv

If this turns up something in /usr/local/bin, then it is possible – even likely – that you installed virtualenv (possibly using an instance of easy_tools or pip) without using your system’s package manager (brew in OP’s case). This was my problem.

Years ago – when I was even more ignorant – I had installed virtualenv and it was masking my system’s package-provided virtualenv.

After removing this old, broken virtualenv, my problems went away.


回答 10

在python3.6中,我python3 -m venv myenv根据文档尝试 了,但是花费了很长时间。因此,非常简单快捷的命令是: python -m venv yourenv 它在python3.6上对我有效。

In python3.6 I tried python3 -m venv myenv, as per the documentation, but it was taking so long. So the very simple and quick command is python -m venv yourenv It worked for me on python3.6.


回答 11

在Mac上,我必须执行以下操作才能使其正常工作。

mkvirtualenv --python=/usr/bin/python3 YourEnvNameHere

On Mac I had to do the following to get it to work.

mkvirtualenv --python=/usr/bin/python3 YourEnvNameHere

回答 12

如果您将python3(brew install python3)与virtualenv burrito一起安装,则可以 mkvirtualenv -p $(which python3) env_name

当然,我知道virtualenv burrito只是一个包装,但是多年来,它对我很有用,减少了一些学习难度。

If you install python3 (brew install python3) along with virtualenv burrito, you can then do mkvirtualenv -p $(which python3) env_name

Of course, I know virtualenv burrito is just a wrapper, but it has served me well over the years, reducing some learning curves.


回答 13

virtualenv --python=/usr/local/bin/python3 <VIRTUAL ENV NAME> 这将为 您的虚拟环境添加python3路径。

virtualenv --python=/usr/local/bin/python3 <VIRTUAL ENV NAME> this will add python3 path for your virtual enviroment.


回答 14

对我有用

virtualenv --no-site-packages --distribute -p /usr/bin/python3 ~/.virtualenvs/py3

It worked for me

virtualenv --no-site-packages --distribute -p /usr/bin/python3 ~/.virtualenvs/py3

回答 15

对于那些在使用Anaconda3(Python 3)时遇到麻烦的人。

你可以用

conda create -n name_of_your_virtualenv python=python_version 

激活环境(Linux,MacOS)

source activate name_of_your_virtualenv

对于Windows

activate name_of_your_virtualenv

For those having troubles while working with Anaconda3 (Python 3).

You could use

conda create -n name_of_your_virtualenv python=python_version 

To activate the environment ( Linux, MacOS)

source activate name_of_your_virtualenv

For Windows

activate name_of_your_virtualenv

回答 16

我尝试了以上所有方法,但仍然没有效果。因此,作为蛮力,我只是重新安装了anaconda,重新安装了virtualenv …,它确实起作用了。

Amans-MacBook-Pro:~ amanmadan$ pip install virtualenv
You are using pip version 6.1.1, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting virtualenv
  Downloading virtualenv-15.0.3-py2.py3-none-any.whl (3.5MB)
    100% |████████████████████████████████| 3.5MB 114kB/s 
Installing collected packages: virtualenv
Successfully installed virtualenv-15.0.3
Amans-MacBook-Pro:python amanmadan$ virtualenv my_env
New python executable in /Users/amanmadan/Documents/HadoopStuff/python/my_env/bin/python
Installing setuptools, pip, wheel...done.
Amans-MacBook-Pro:python amanmadan$ 

I tried all the above stuff, it still didn’t work. So as a brute force, I just re-installed the anaconda, re-installed the virtualenv… and it worked.

Amans-MacBook-Pro:~ amanmadan$ pip install virtualenv
You are using pip version 6.1.1, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting virtualenv
  Downloading virtualenv-15.0.3-py2.py3-none-any.whl (3.5MB)
    100% |████████████████████████████████| 3.5MB 114kB/s 
Installing collected packages: virtualenv
Successfully installed virtualenv-15.0.3
Amans-MacBook-Pro:python amanmadan$ virtualenv my_env
New python executable in /Users/amanmadan/Documents/HadoopStuff/python/my_env/bin/python
Installing setuptools, pip, wheel...done.
Amans-MacBook-Pro:python amanmadan$ 

回答 17

我想将python 2.7.5保留为Centos 7的默认版本,但在虚拟环境中将python 3.6.1与python 2.x中的其他虚拟环境一起运行

我发现以下链接是最新python版本(python 3.6.1)的最佳解决方案 https://www.digitalocean.com/community/tutorial_series/how-to-install-and-set-up-a-local-programming -for-python-3环境。它显示了不同平台的步骤,但是基本步骤是

  1. 为您的平台安装python3.x(如果不存在)
  2. 为您的平台安装python3.x-devel
  3. 在python 3.x中创建虚拟环境(例如$ python3.6 -m venv virenv_test_p3 /)
  4. 激活python 3.x的测试环境(例如源virenv_test_p3 / bin / activate)
  5. 安装要在新的python 3虚拟环境中使用且受支持的软件包(例如pip install Django == 1.11.2)

I wanted to keep python 2.7.5 as default version on Centos 7 but have python 3.6.1 in a virtual environment running alongside other virtual environments in python 2.x

I found the below link the best solution for the newest python version ( python 3.6.1) https://www.digitalocean.com/community/tutorial_series/how-to-install-and-set-up-a-local-programming-environment-for-python-3. It shows the steps for different platforms but the basic steps are

  1. Install python3.x (if not present) for your platform
  2. Install python3.x-devel for your platform
  3. Create virtual environment in python 3.x (for example $ python3.6 -m venv virenv_test_p3/ )
  4. Activate the testenvironment for python 3.x (for example source virenv_test_p3/bin/activate)
  5. Install the packages which you want to use in your new python 3 virtual environment and which are supported ( for example pip install Django==1.11.2)

回答 18

下面的简单命令可以使用3.5版创建虚拟环境

apt-get install python3-venv

python3.5 -m venv <your env name>

如果您希望虚拟环境版本为3.6

python3.6 -m venv <your env name>

The below simple commands can create a virtual env with version 3.5

apt-get install python3-venv

python3.5 -m venv <your env name>

if you want virtual env version as 3.6

python3.6 -m venv <your env name>

回答 19

对于正在使用pipenv并想要安装特定版本的用户:

pipenv install --python 3.6

For those of you who are using pipenv and want to install specific version:

pipenv install --python 3.6

回答 20

由于存在与miniconda3安装冲突的问题,因此出现了相同的错误,因此当您键入“哪个virtualenv”并且安装了miniconda并指向该安装时,您可以将其删除(如果您喜欢我并且没有移动)或更改环境变量以指向所需的安装。

I got the same error due to it being a conflict with miniconda3 install so when you type “which virtualenv” and if you’ve installed miniconda and it’s pointing to that install you can either remove it (if your like me and haven’t moved to it yet) or change your environment variable to point to the install you want.


回答 21

在Windows命令行上,以下内容对我有用。首先找出您的python可执行文件所在的位置:

where python

这会将路径输出到系统上其他python.exe的路径。这是我的:

C:\Users\carandangc\Anaconda3\python.exe
C:\Python27\python.exe

因此,对于Python3而言,这位于我的第一个路径中,因此我进入了要在其中创建虚拟环境文件夹的应用程序的根文件夹。然后,我运行以下命令,其中包括我的Python3可执行文件的路径,将我的虚拟环境命名为“ venv”:

virtualenv --python=/Users/carandangc/Anaconda3/python.exe venv

接下来,激活虚拟环境:

call venv\Scripts\activate.bat

最后,安装此虚拟环境的依赖项:

pip install -r requirements.txt

如果您知道虚拟环境中应用程序所需的库/模块,则可以手动填充此requirements.txt。如果您的应用程序在另一个环境中运行,则可以通过运行以下命令(在运行它的环境中的cd到应用程序文件夹中)来自动生成依赖项:

pip freeze > requirements.txt

然后,一旦您具有“冻结”的requests.txt,则可以使用以下命令(在cd到应用程序文件夹之后)在另一台计算机或干净的环境中安装需求:

pip install -r requirements.txt

要在虚拟环境中查看python版本,请运行:

python --version

然后,瞧……您的Python3正在虚拟环境中运行。为我输出:

Python 3.7.2

On Windows command line, the following worked for me. First find out where your python executables are located:

where python

This will output the paths to the different python.exe on your system. Here were mine:

C:\Users\carandangc\Anaconda3\python.exe
C:\Python27\python.exe

So for Python3, this was located in the first path for me, so I cd to the root folder of the application where I want to create a virtual environment folder. Then I run the following which includes the path to my Python3 executable, naming my virtual environment ‘venv’:

virtualenv --python=/Users/carandangc/Anaconda3/python.exe venv

Next, activate the virtual environment:

call venv\Scripts\activate.bat

Finally, install the dependencies for this virtual environment:

pip install -r requirements.txt

This requirements.txt could be populated manually if you know the libraries/modules needed for your application in the virtual environment. If you had the application running in another environment, then you can automatically produce the dependencies by running the following (cd to the application folder in the environment where it is working):

pip freeze > requirements.txt

Then once you have the requirements.txt that you have ‘frozen’, then you can install the requirements on another machine or clean environment with the following (after cd to the application folder):

pip install -r requirements.txt

To see your python version in the virtual environment, run:

python --version

Then voila…you have your Python3 running in your virtual environment. Output for me:

Python 3.7.2

如何在Python中将字典键作为列表返回?

问题:如何在Python中将字典键作为列表返回?

Python 2.7中,我可以将字典作为列表获取:

>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]

现在,在Python> = 3.3中,我得到如下信息:

>>> newdict.keys()
dict_keys([1, 2, 3])

因此,我必须这样做以获得列表:

newlist = list()
for i in newdict.keys():
    newlist.append(i)

我想知道,是否有更好的方法在Python 3中返回列表?

In Python 2.7, I could get dictionary keys, values, or items as a list:

>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]

Now, in Python >= 3.3, I get something like this:

>>> newdict.keys()
dict_keys([1, 2, 3])

So, I have to do this to get a list:

newlist = list()
for i in newdict.keys():
    newlist.append(i)

I’m wondering, is there a better way to return a list in Python 3?


回答 0

尝试list(newdict.keys())

这会将dict_keys对象转换为列表。

另一方面,您应该问自己是否重要。Python的编码方式是假设鸭子输入(如果它看起来像鸭子,而像鸭子一样嘎嘎叫,那就是鸭子)。在dict_keys大多数情况下,该对象的作用类似于列表。例如:

for key in newdict.keys():
  print(key)

显然,插入运算符可能不起作用,但是对于字典关键字列表而言,这并没有多大意义。

Try list(newdict.keys()).

This will convert the dict_keys object to a list.

On the other hand, you should ask yourself whether or not it matters. The Pythonic way to code is to assume duck typing (if it looks like a duck and it quacks like a duck, it’s a duck). The dict_keys object will act like a list for most purposes. For instance:

for key in newdict.keys():
  print(key)

Obviously, insertion operators may not work, but that doesn’t make much sense for a list of dictionary keys anyway.


回答 1

Python> = 3.5替代方法:解压缩为列表文字 [*newdict]

Python 3.5引入了新的拆包概括(PEP 448),使您现在可以轻松进行以下操作:

>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]

与解压缩的对象可*任何可迭代的对象一起使用,并且由于字典在迭代过程中会返回其键,因此您可以在列表文字中使用它轻松创建列表。

添加.keys()ie [*newdict.keys()]可能有助于使您的意图更加明确,尽管这将花费您函数查找和调用的费用。(实际上,这不是您真正应该担心的事情)。

*iterable语法类似于做list(iterable)其行为最初记录在呼叫部分 Python的参考手册。对于PEP 448,放宽了对*iterable可能出现的位置的限制,使其也可以放置在列表,集合和元组文字中,“ 表达式”列表上的参考手册也进行了更新以说明这一点。


尽管这等效于list(newdict)它更快(至少对于小型词典而言),因为实际上没有执行任何函数调用:

%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop

%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop

%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop

对于较大的字典,速度几乎是相同的(遍历大量集合的开销胜过了函数调用的小开销)。


您可以用类似的方式创建元组和字典键集:

>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}

在元组的情况下要小心尾随逗号!

Python >= 3.5 alternative: unpack into a list literal [*newdict]

New unpacking generalizations (PEP 448) were introduced with Python 3.5 allowing you to now easily do:

>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]

Unpacking with * works with any object that is iterable and, since dictionaries return their keys when iterated through, you can easily create a list by using it within a list literal.

Adding .keys() i.e [*newdict.keys()] might help in making your intent a bit more explicit though it will cost you a function look-up and invocation. (which, in all honesty, isn’t something you should really be worried about).

The *iterable syntax is similar to doing list(iterable) and its behaviour was initially documented in the Calls section of the Python Reference manual. With PEP 448 the restriction on where *iterable could appear was loosened allowing it to also be placed in list, set and tuple literals, the reference manual on Expression lists was also updated to state this.


Though equivalent to list(newdict) with the difference that it’s faster (at least for small dictionaries) because no function call is actually performed:

%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop

%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop

%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop

with larger dictionaries the speed is pretty much the same (the overhead of iterating through a large collection trumps the small cost of a function call).


In a similar fashion, you can create tuples and sets of dictionary keys:

>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}

beware of the trailing comma in the tuple case!


回答 2

list(newdict)在Python 2和Python 3中均可使用,在中提供了键的简单列表newdictkeys()没必要 (:

list(newdict) works in both Python 2 and Python 3, providing a simple list of the keys in newdict. keys() isn’t necessary. (:


回答 3

在“鸭子类型”定义上有一点点偏离- dict.keys()返回一个可迭代的对象,而不是类似列表的对象。它可以在任何可迭代的地方都可以使用-列表不能在任何地方使用。列表也是可迭代的,但可迭代的不是列表(或序列…)

在实际的用例中,与字典中的键有关的最常见的事情是遍历它们,因此这很有意义。如果确实需要它们作为清单,则可以调用list()

非常相似zip()-在大多数情况下,它会被迭代-为什么创建一个新的元组列表只是为了对其进行迭代,然后又将其丢弃?

这是python中使用更多迭代器(和生成器),而不是到处都是列表副本的一种大趋势的一部分。

dict.keys() 不过,应该可以理解-仔细检查是否有错别字或其他内容…对我来说效果很好:

>>> d = dict(zip(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'], [None, None]))
>>> [key.split(", ") for key in d.keys()]
[['Sounder V Depth', 'F'], ['Vessel Latitude', 'Degrees-Minutes']]

A bit off on the “duck typing” definition — dict.keys() returns an iterable object, not a list-like object. It will work anywhere an iterable will work — not any place a list will. a list is also an iterable, but an iterable is NOT a list (or sequence…)

In real use-cases, the most common thing to do with the keys in a dict is to iterate through them, so this makes sense. And if you do need them as a list you can call list().

Very similarly for zip() — in the vast majority of cases, it is iterated through — why create an entire new list of tuples just to iterate through it and then throw it away again?

This is part of a large trend in python to use more iterators (and generators), rather than copies of lists all over the place.

dict.keys() should work with comprehensions, though — check carefully for typos or something… it works fine for me:

>>> d = dict(zip(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'], [None, None]))
>>> [key.split(", ") for key in d.keys()]
[['Sounder V Depth', 'F'], ['Vessel Latitude', 'Degrees-Minutes']]

回答 4

您还可以使用列表推导

>>> newdict = {1:0, 2:0, 3:0}
>>> [k  for  k in  newdict.keys()]
[1, 2, 3]

或更短一点

>>> [k  for  k in  newdict]
[1, 2, 3]

注意:在3.7版以下的版本中,不能保证订购(订购仍然只是CPython 3.6的实现细节)。

You can also use a list comprehension:

>>> newdict = {1:0, 2:0, 3:0}
>>> [k  for  k in  newdict.keys()]
[1, 2, 3]

Or, shorter,

>>> [k  for  k in  newdict]
[1, 2, 3]

Note: Order is not guaranteed on versions under 3.7 (ordering is still only an implementation detail with CPython 3.6).


回答 5

不使用该keys方法转换为列表使其更具可读性:

list(newdict)

并且,当遍历字典时,不需要keys()

for key in newdict:
    print key

除非您要在循环中进行修改,否则将需要预先创建的键列表:

for key in list(newdict):
    del newdict[key]

在Python 2上,使用会产生少量性能提升keys()

Converting to a list without using the keys method makes it more readable:

list(newdict)

and, when looping through dictionaries, there’s no need for keys():

for key in newdict:
    print key

unless you are modifying it within the loop which would require a list of keys created beforehand:

for key in list(newdict):
    del newdict[key]

On Python 2 there is a marginal performance gain using keys().


回答 6

如果您需要单独存储密钥,那么此解决方案使用扩展的可迭代拆包(python3.x +),与迄今为止提供的所有其他解决方案相比,它的键入次数更少。

newdict = {1: 0, 2: 0, 3: 0}
*k, = newdict

k
# [1, 2, 3]

            ╒═══════════════╤═════════════════════════════════════════╕
             k = list(d)      9 characters (excluding whitespace)   
            ├───────────────┼─────────────────────────────────────────┤
             k = [*d]         6 characters                          
            ├───────────────┼─────────────────────────────────────────┤
             *k, = d          5 characters                          
            ╘═══════════════╧═════════════════════════════════════════╛

If you need to store the keys separately, here’s a solution that requires less typing than every other solution presented thus far, using Extended Iterable Unpacking (python3.x+).

newdict = {1: 0, 2: 0, 3: 0}
*k, = newdict

k
# [1, 2, 3]

            ╒═══════════════╤═════════════════════════════════════════╕
            │ k = list(d)   │   9 characters (excluding whitespace)   │
            ├───────────────┼─────────────────────────────────────────┤
            │ k = [*d]      │   6 characters                          │
            ├───────────────┼─────────────────────────────────────────┤
            │ *k, = d       │   5 characters                          │
            ╘═══════════════╧═════════════════════════════════════════╛

回答 7

我可以想到两种从字典中提取键的方法。

方法1:- 使用.keys()方法获取密钥,然后将其转换为列表。

some_dict = {1: 'one', 2: 'two', 3: 'three'}
list_of_keys = list(some_dict.keys())
print(list_of_keys)
-->[1,2,3]

方法2:- 创建一个空列表,然后通过循环将键附加到列表中。您也可以通过此循环获取值(仅将.keys()用于键,将.items()用于键和值提取)

list_of_keys = []
list_of_values = []
for key,val in some_dict.items():
    list_of_keys.append(key)
    list_of_values.append(val)

print(list_of_keys)
-->[1,2,3]

print(list_of_values)
-->['one','two','three']

I can think of 2 ways in which we can extract the keys from the dictionary.

Method 1: – To get the keys using .keys() method and then convert it to list.

some_dict = {1: 'one', 2: 'two', 3: 'three'}
list_of_keys = list(some_dict.keys())
print(list_of_keys)
-->[1,2,3]

Method 2: – To create an empty list and then append keys to the list via a loop. You can get the values with this loop as well (use .keys() for just keys and .items() for both keys and values extraction)

list_of_keys = []
list_of_values = []
for key,val in some_dict.items():
    list_of_keys.append(key)
    list_of_values.append(val)

print(list_of_keys)
-->[1,2,3]

print(list_of_values)
-->['one','two','three']

如何在不停止程序的情况下打印完整的回溯?

问题:如何在不停止程序的情况下打印完整的回溯?

我正在编写一个程序,该程序可以解析10个网站,找到数据文件,保存文件,然后解析它们以生成可以在NumPy库中轻松使用的数据。有万吨通过不良链接,不好的XML,缺项,其他的事情我还没有进行分类文件遇到错误的。我最初制作该程序来处理以下错误:

try:
    do_stuff()
except:
    pass

但是现在我想记录错误:

try:
    do_stuff()
except Exception, err:
    print Exception, err

请注意,这是打印到日志文件中以供以后查看。这通常会打印非常无用的数据。我想要的是在错误触发时打印完全相同的行,而没有try-except拦截异常,但是我不希望它暂停我的程序,因为它嵌套在我想要的一系列for循环中看到完成。

I’m writing a program that parses 10 websites, locates data files, saves the files, and then parses them to make data that can be readily used in the NumPy library. There are tons of errors this file encounters through bad links, poorly formed XML, missing entries, and other things I’ve yet to categorize. I initially made this program to handle errors like this:

try:
    do_stuff()
except:
    pass

But now I want to log errors:

try:
    do_stuff()
except Exception, err:
    print Exception, err

Note this is printing to a log file for later review. This usually prints very useless data. What I want is to print the exact same lines printed when the error triggers without the try-except intercepting the exception, but I don’t want it to halt my program since it is nested in a series of for loops that I would like to see to completion.


回答 0

其他一些答案已经指出了追溯模块。

请注意,使用print_exc,在某些特殊情况下,您将无法获得预期的结果。在Python 2.x中:

import traceback

try:
    raise TypeError("Oups!")
except Exception, err:
    try:
        raise TypeError("Again !?!")
    except:
        pass

    traceback.print_exc()

…将显示最后一个异常的回溯:

Traceback (most recent call last):
  File "e.py", line 7, in <module>
    raise TypeError("Again !?!")
TypeError: Again !?!

如果您确实需要访问原始的追溯,一种解决方案是将异常信息exc_info本地变量中返回,并使用来显示它print_exception

import traceback
import sys

try:
    raise TypeError("Oups!")
except Exception, err:
    try:
        exc_info = sys.exc_info()

        # do you usefull stuff here
        # (potentially raising an exception)
        try:
            raise TypeError("Again !?!")
        except:
            pass
        # end of useful stuff


    finally:
        # Display the *original* exception
        traceback.print_exception(*exc_info)
        del exc_info

生产:

Traceback (most recent call last):
  File "t.py", line 6, in <module>
    raise TypeError("Oups!")
TypeError: Oups!

很少有这个陷阱:

  • 从文档sys_info

    在处理异常的函数中将回溯返回值分配给局部变量将导致循环引用。这将防止垃圾回收由同一函数中的局部变量或回溯引用的任何内容。[…] 如果确实需要回溯,请确保在使用后将其删除(最好通过try … finally语句完成)

  • 但是,根据同一文档:

    从Python 2.2开始,启用垃圾收集并使其无法访问时,会自动回收此类循环,但是避免创建循环仍然更加有效。


另一方面,通过允许您访问异常关联的回溯,Python 3产生了一个不太令人惊讶的结果:

import traceback

try:
    raise TypeError("Oups!")
except Exception as err:
    try:
        raise TypeError("Again !?!")
    except:
        pass

    traceback.print_tb(err.__traceback__)

…将显示:

  File "e3.py", line 4, in <module>
    raise TypeError("Oups!")

Some other answer have already pointed out the traceback module.

Please notice that with print_exc, in some corner cases, you will not obtain what you would expect. In Python 2.x:

import traceback

try:
    raise TypeError("Oups!")
except Exception, err:
    try:
        raise TypeError("Again !?!")
    except:
        pass

    traceback.print_exc()

…will display the traceback of the last exception:

Traceback (most recent call last):
  File "e.py", line 7, in <module>
    raise TypeError("Again !?!")
TypeError: Again !?!

If you really need to access the original traceback one solution is to cache the exception infos as returned from exc_info in a local variable and display it using print_exception:

import traceback
import sys

try:
    raise TypeError("Oups!")
except Exception, err:
    try:
        exc_info = sys.exc_info()

        # do you usefull stuff here
        # (potentially raising an exception)
        try:
            raise TypeError("Again !?!")
        except:
            pass
        # end of useful stuff


    finally:
        # Display the *original* exception
        traceback.print_exception(*exc_info)
        del exc_info

Producing:

Traceback (most recent call last):
  File "t.py", line 6, in <module>
    raise TypeError("Oups!")
TypeError: Oups!

Few pitfalls with this though:

  • From the doc of sys_info:

    Assigning the traceback return value to a local variable in a function that is handling an exception will cause a circular reference. This will prevent anything referenced by a local variable in the same function or by the traceback from being garbage collected. […] If you do need the traceback, make sure to delete it after use (best done with a try … finally statement)

  • but, from the same doc:

    Beginning with Python 2.2, such cycles are automatically reclaimed when garbage collection is enabled and they become unreachable, but it remains more efficient to avoid creating cycles.


On the other hand, by allowing you to access the traceback associated with an exception, Python 3 produce a less surprising result:

import traceback

try:
    raise TypeError("Oups!")
except Exception as err:
    try:
        raise TypeError("Again !?!")
    except:
        pass

    traceback.print_tb(err.__traceback__)

… will display:

  File "e3.py", line 4, in <module>
    raise TypeError("Oups!")

回答 1

traceback.format_exc()sys.exc_info()会产生更多信息(如果您想要的话)。

import traceback
import sys

try:
    do_stuff()
except Exception:
    print(traceback.format_exc())
    # or
    print(sys.exc_info()[2])

traceback.format_exc() or sys.exc_info() will yield more info if that’s what you want.

import traceback
import sys

try:
    do_stuff()
except Exception:
    print(traceback.format_exc())
    # or
    print(sys.exc_info()[2])

回答 2

如果您正在调试,并且只想查看当前的堆栈跟踪,则可以简单地调用:

traceback.print_stack()

无需为了再次捕获而手动引发异常。

If you’re debugging and just want to see the current stack trace, you can simply call:

traceback.print_stack()

There’s no need to manually raise an exception just to catch it again.


回答 3

如何在不停止程序的情况下打印完整的回溯?

当您不想因错误而暂停程序时,需要使用try / except处理该错误:

try:
    do_something_that_might_error()
except Exception as error:
    handle_the_error(error)

要提取完整的追溯,我们将使用traceback标准库中的模块:

import traceback

并创建一个相当复杂的堆栈跟踪以演示我们获得了完整的堆栈跟踪:

def raise_error():
    raise RuntimeError('something bad happened!')

def do_something_that_might_error():
    raise_error()

列印

打印完整的回溯,请使用以下traceback.print_exc方法:

try:
    do_something_that_might_error()
except Exception as error:
    traceback.print_exc()

哪些打印:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

比打印,记录更好:

但是,最佳实践是为模块设置一个记录器。它将知道模块的名称,并能够更改级别(在其他属性中,例如处理程序)

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

在这种情况下,您将需要该logger.exception函数:

try:
    do_something_that_might_error()
except Exception as error:
    logger.exception(error)

哪个日志:

ERROR:__main__:something bad happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

或者,也许您只想要字符串,在这种情况下,您将需要traceback.format_exc函数:

try:
    do_something_that_might_error()
except Exception as error:
    logger.debug(traceback.format_exc())

哪个日志:

DEBUG:__main__:Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

结论

对于这三个选项,我们看到的输出与发生错误时的输出相同:

>>> do_something_that_might_error()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

How to print the full traceback without halting the program?

When you don’t want to halt your program on an error, you need to handle that error with a try/except:

try:
    do_something_that_might_error()
except Exception as error:
    handle_the_error(error)

To extract the full traceback, we’ll use the traceback module from the standard library:

import traceback

And to create a decently complicated stacktrace to demonstrate that we get the full stacktrace:

def raise_error():
    raise RuntimeError('something bad happened!')

def do_something_that_might_error():
    raise_error()

Printing

To print the full traceback, use the traceback.print_exc method:

try:
    do_something_that_might_error()
except Exception as error:
    traceback.print_exc()

Which prints:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

Better than printing, logging:

However, a best practice is to have a logger set up for your module. It will know the name of the module and be able to change levels (among other attributes, such as handlers)

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

In which case, you’ll want the logger.exception function instead:

try:
    do_something_that_might_error()
except Exception as error:
    logger.exception(error)

Which logs:

ERROR:__main__:something bad happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

Or perhaps you just want the string, in which case, you’ll want the traceback.format_exc function instead:

try:
    do_something_that_might_error()
except Exception as error:
    logger.debug(traceback.format_exc())

Which logs:

DEBUG:__main__:Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

Conclusion

And for all three options, we see we get the same output as when we have an error:

>>> do_something_that_might_error()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

回答 4

首先,不要用printS表示日志记录,有非稳态,证明和深思熟虑的STDLIB模块,这样做:logging。您绝对应该使用它。

其次,当存在本机且简单的方法时,不要试图将无关的工具弄得一团糟。这里是:

log = logging.getLogger(__name__)

try:
    call_code_that_fails()
except MyError:
    log.exception('Any extra info you want to see in your logs')

而已。现在完成了。

对任何对引擎盖如何工作感兴趣的人的解释

什么log.exception是真正做只是为了通话log.error(即记录与级别的事件ERROR,并打印回溯然后。

为什么会更好?

好,这是一些注意事项:

  • 这是正确的 ;
  • 这很简单;
  • 很简单。

为什么没有人可以使用traceback记录仪exc_info=True或与其通话,或者弄脏记录仪sys.exc_info

好吧,只是因为!它们全都出于不同的目的而存在。例如,traceback.print_exc的输出与解释器本身产生的回溯有些不同。如果您使用它,则会使任何人阅读您的日志感到困惑,他们会撞到他们的头。

传递exc_info=True日志记录是不合适的。但是,当捕获可恢复的错误并且您还希望使用INFO回溯记录它们(使用例如级别)时,它很有用,因为它log.exception只会生成一个级别的日志- ERROR

而且,您绝对应该尽可能避免混乱sys.exc_info。它不是一个公共接口,而是一个内部接口- 如果您完全知道自己在做什么,就可以使用它。它不仅仅用于打印exceptions。

First, don’t use prints for logging, there is astable, proven and well-thought out stdlib module to do that: logging. You definitely should use it instead.

Second, don’t be tempted to do a mess with unrelated tools when there is native and simple approach. Here it is:

log = logging.getLogger(__name__)

try:
    call_code_that_fails()
except MyError:
    log.exception('Any extra info you want to see in your logs')

That’s it. You are done now.

Explanation for anyone who is interested in how things work under the hood

What log.exception is actually doing is just a call to log.error (that is, log event with level ERROR) and print traceback then.

Why is it better?

Well, here is some considerations:

  • it is just right;
  • it is straightforward;
  • it is simple.

Why should nobody use traceback or call logger with exc_info=True or get their hands dirty with sys.exc_info?

Well, just because! They all exist for different purposes. For example, traceback.print_exc‘s output is a little bit different from tracebacks produced by the interpreter itself. If you use it, you will confuse anyone who reads your logs, they will be banging their heads against them.

Passing exc_info=True to log calls is just inappropriate. But, it is useful when catching recoverable errors and you want to log them (using, e.g INFO level) with tracebacks as well, because log.exception produces logs of only one level – ERROR.

And you definitely should avoid messing with sys.exc_info as much as you can. It’s just not a public interface, it’s an internal one – you can use it if you definitely know what you are doing. It is not intended for just printing exceptions.


回答 5

除了@Aaron Hall的答案外,如果您正在记录日志,但又不想使用logging.exception()(由于它记录为ERROR级别),则可以使用较低级别并通过exc_info=True。例如

try:
    do_something_that_might_error()
except Exception:
    logger.info('General exception noted.', exc_info=True)

In addition to @Aaron Hall’s answer, if you are logging, but don’t want to use logging.exception() (since it logs at the ERROR level), you can use a lower level and pass exc_info=True. e.g.

try:
    do_something_that_might_error()
except Exception:
    logger.info('General exception noted.', exc_info=True)

回答 6

为了得到精确的堆栈跟踪,作为一个字符串,已如果没有尝试/除非在那里步过它,只是把这个在除块捕获违规的异常上升。

desired_trace = traceback.format_exc(sys.exc_info())

这是使用方法(假设flaky_func已定义,并log调用了您喜欢的日志系统):

import traceback
import sys

try:
    flaky_func()
except KeyboardInterrupt:
    raise
except Exception:
    desired_trace = traceback.format_exc(sys.exc_info())
    log(desired_trace)

捕获并重新引发KeyboardInterrupts 是一个好主意,这样您仍然可以使用Ctrl-C终止程序。日志记录不在问题范围之内,但是不错的选择是loggingsystraceback模块的文档。

To get the precise stack trace, as a string, that would have been raised if no try/except were there to step over it, simply place this in the except block that catches the offending exception.

desired_trace = traceback.format_exc(sys.exc_info())

Here’s how to use it (assuming flaky_func is defined, and log calls your favorite logging system):

import traceback
import sys

try:
    flaky_func()
except KeyboardInterrupt:
    raise
except Exception:
    desired_trace = traceback.format_exc(sys.exc_info())
    log(desired_trace)

It’s a good idea to catch and re-raise KeyboardInterrupts, so that you can still kill the program using Ctrl-C. Logging is outside the scope of the question, but a good option is logging. Documentation for the sys and traceback modules.


回答 7

您需要将try / except放到可能发生错误的最内部循环中,即

for i in something:
    for j in somethingelse:
        for k in whatever:
            try:
                something_complex(i, j, k)
            except Exception, e:
                print e
        try:
            something_less_complex(i, j)
        except Exception, e:
            print e

… 等等

换句话说,您需要将可能在try / except中失败的语句包装在尽可能多的内部循环中,并尽可能不具体。

You will need to put the try/except inside the most innerloop where the error may occur, i.e.

for i in something:
    for j in somethingelse:
        for k in whatever:
            try:
                something_complex(i, j, k)
            except Exception, e:
                print e
        try:
            something_less_complex(i, j)
        except Exception, e:
            print e

… and so on

In other words, you will need to wrap statements that may fail in try/except as specific as possible, in the most inner-loop as possible.


回答 8

关于此答案的评论:print(traceback.format_exc())对我来说,做得更好traceback.print_exc()。对于后者,hello有时会奇怪地将其与回溯文本“混合”,例如,如果两者都想同时写入stdout或stderr,则会产生奇怪的输出(至少在文本编辑器内部进行构建并在“构建结果”面板)。

追溯(最近一次通话):
文件“ C:\ Users \ User \ Desktop \ test.py”,第7行,在
地狱 do_stuff()
文件“ C:\ Users \ User \ Desktop \ test.py”,第4行,在do_stuff
1/0
ZeroDivisionError中:整数除或以零为模的
o
[在0.1s内完成]

所以我用:

import traceback, sys

def do_stuff():
    1/0

try:
    do_stuff()
except Exception:
    print(traceback.format_exc())
    print('hello')

A remark about this answer‘s comments: print(traceback.format_exc()) does a better job for me than traceback.print_exc(). With the latter, the hello is sometimes strangely “mixed” with the traceback text, like if both want to write to stdout or stderr at the same time, producing weird output (at least when building from inside a text editor and viewing the output in the “Build results” panel).

Traceback (most recent call last):
File “C:\Users\User\Desktop\test.py”, line 7, in
hell do_stuff()
File “C:\Users\User\Desktop\test.py”, line 4, in do_stuff
1/0
ZeroDivisionError: integer division or modulo by zero
o
[Finished in 0.1s]

So I use:

import traceback, sys

def do_stuff():
    1/0

try:
    do_stuff()
except Exception:
    print(traceback.format_exc())
    print('hello')

回答 9

我在其他任何答案中都没有提到这一点。如果出于某种原因要传递Exception对象…

在Python 3.5+中,您可以使用traceback.TracebackException.from_exception()从Exception对象获取跟踪。例如:

import traceback


def stack_lvl_3():
    raise Exception('a1', 'b2', 'c3')


def stack_lvl_2():
    try:
        stack_lvl_3()
    except Exception as e:
        # raise
        return e


def stack_lvl_1():
    e = stack_lvl_2()
    return e

e = stack_lvl_1()

tb1 = traceback.TracebackException.from_exception(e)
print(''.join(tb1.format()))

但是,以上代码导致:

Traceback (most recent call last):
  File "exc.py", line 10, in stack_lvl_2
    stack_lvl_3()
  File "exc.py", line 5, in stack_lvl_3
    raise Exception('a1', 'b2', 'c3')
Exception: ('a1', 'b2', 'c3')

这只是堆栈的两个级别,与在引发异常stack_lvl_2()但未拦截异常的情况下在屏幕上显示的内容相反(取消注释# raise行)。

据我了解,这是因为stack_lvl_3()在这种情况下,异常在引发时仅记录堆栈的当前级别。随着它在堆栈中的传递,它被添加了更多的层次__traceback__。但是我们在中截获了它stack_lvl_2(),这意味着它要记录的只是3级和2级。要获得在stdout上打印的完整轨迹,我们必须在最高(最低?)级捕获它:

import traceback


def stack_lvl_3():
    raise Exception('a1', 'b2', 'c3')


def stack_lvl_2():
    stack_lvl_3()


def stack_lvl_1():
    stack_lvl_2()


try:
    stack_lvl_1()
except Exception as exc:
    tb = traceback.TracebackException.from_exception(exc)

print('Handled at stack lvl 0')
print(''.join(tb.stack.format()))

结果是:

Handled at stack lvl 0
  File "exc.py", line 17, in <module>
    stack_lvl_1()
  File "exc.py", line 13, in stack_lvl_1
    stack_lvl_2()
  File "exc.py", line 9, in stack_lvl_2
    stack_lvl_3()
  File "exc.py", line 5, in stack_lvl_3
    raise Exception('a1', 'b2', 'c3')

注意,堆栈打印不同,缺少第一行和最后一行。因为是不同的format()

截取该异常离生成点越远越好,这使得代码更简单,同时也提供了更多信息。

I don’t see this mentioned in any of the other answers. If you’re passing around an Exception object for whatever reason…

In Python 3.5+ you can get a trace from an Exception object using traceback.TracebackException.from_exception(). For example:

import traceback


def stack_lvl_3():
    raise Exception('a1', 'b2', 'c3')


def stack_lvl_2():
    try:
        stack_lvl_3()
    except Exception as e:
        # raise
        return e


def stack_lvl_1():
    e = stack_lvl_2()
    return e

e = stack_lvl_1()

tb1 = traceback.TracebackException.from_exception(e)
print(''.join(tb1.format()))

However, the above code results in:

Traceback (most recent call last):
  File "exc.py", line 10, in stack_lvl_2
    stack_lvl_3()
  File "exc.py", line 5, in stack_lvl_3
    raise Exception('a1', 'b2', 'c3')
Exception: ('a1', 'b2', 'c3')

This is just two levels of the stack, as opposed to what would have been printed on screen had the exception been raised in stack_lvl_2() and not intercepted (uncomment the # raise line).

As I understand it, that’s because an exception records only the current level of the stack when it is raised, stack_lvl_3() in this case. As it’s passed back up through the stack, more levels are being added to its __traceback__. But we intercepted it in stack_lvl_2(), meaning all it got to record was levels 3 and 2. To get the full trace as printed on stdout we’d have to catch it at the highest (lowest?) level:

import traceback


def stack_lvl_3():
    raise Exception('a1', 'b2', 'c3')


def stack_lvl_2():
    stack_lvl_3()


def stack_lvl_1():
    stack_lvl_2()


try:
    stack_lvl_1()
except Exception as exc:
    tb = traceback.TracebackException.from_exception(exc)

print('Handled at stack lvl 0')
print(''.join(tb.stack.format()))

Which results in:

Handled at stack lvl 0
  File "exc.py", line 17, in <module>
    stack_lvl_1()
  File "exc.py", line 13, in stack_lvl_1
    stack_lvl_2()
  File "exc.py", line 9, in stack_lvl_2
    stack_lvl_3()
  File "exc.py", line 5, in stack_lvl_3
    raise Exception('a1', 'b2', 'c3')

Notice that the stack print is different, the first and last lines are missing. Because it’s a different format().

Intercepting the exception as far away from the point where it was raised as possible makes for simpler code while also giving more information.


回答 10

您需要回溯模块。它可以让您像Python通常一样打印堆栈转储。特别是,print_last函数将打印最后的异常和堆栈跟踪。

You want the traceback module. It will let you print stack dumps like Python normally does. In particular, the print_last function will print the last exception and a stack trace.


回答 11

从异常对象以字符串形式获取完整的追溯 traceback.format_exception

如果只有异常对象,则可以使用以下命令从Python 3中的代码的任何点以字符串形式获取跟踪:

import traceback

''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))

完整示例:

#!/usr/bin/env python3

import traceback

def f():
    g()

def g():
    raise Exception('asdf')

try:
    g()
except Exception as e:
    exc = e

tb_str = ''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))
print(tb_str)

输出:

Traceback (most recent call last):
  File "./main.py", line 12, in <module>
    g()
  File "./main.py", line 9, in g
    raise Exception('asdf')
Exception: asdf

文档:https : //docs.python.org/3.7/library/traceback.html#traceback.format_exception

另请参阅:从异常对象中提取回溯信息

在Python 3.7.3中测试。

Get the full traceback as a string from the exception object with traceback.format_exception

If you only have the exception object, you can get the traceback as a string from any point of the code in Python 3 with:

import traceback

''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))

Full example:

#!/usr/bin/env python3

import traceback

def f():
    g()

def g():
    raise Exception('asdf')

try:
    g()
except Exception as e:
    exc = e

tb_str = ''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))
print(tb_str)

Output:

Traceback (most recent call last):
  File "./main.py", line 12, in <module>
    g()
  File "./main.py", line 9, in g
    raise Exception('asdf')
Exception: asdf

Documentation: https://docs.python.org/3.7/library/traceback.html#traceback.format_exception

See also: Extract traceback info from an exception object

Tested in Python 3.7.3.


回答 12

如果您已经有一个Error对象,并且想要打印整个内容,则需要进行以下稍微尴尬的调用:

import traceback
traceback.print_exception(type(err), err, err.__traceback__)

是的,print_exception需要三个位置参数:异常的类型,实际的异常对象以及异常自己的内部回溯属性。

在python 3.5或更高版本中,type(err)是可选的…但是它是一个位置参数,因此您仍然必须在其位置显式传递None。

traceback.print_exception(None, err, err.__traceback__)

我不知道为什么所有这些都不是唯一的traceback.print_exception(err)。为什么您要打印出错误以及与该错误无关的回溯,这超出了我的范围。

If you have an Error object already, and you want to print the whole thing, you need to make this slightly awkward call:

import traceback
traceback.print_exception(type(err), err, err.__traceback__)

That’s right, print_exception takes three positional arguments: The type of the exception, the actual exception object, and the exception’s own internal traceback property.

In python 3.5 or later, the type(err) is optional… but it’s a positional argument, so you still have to explicitly pass None in its place.

traceback.print_exception(None, err, err.__traceback__)

I have no idea why all of this isn’t just traceback.print_exception(err). Why you would ever want to print out an error, along with a traceback other than the one that belongs to that error, is beyond me.


您如何测试Python函数引发异常?

问题:您如何测试Python函数引发异常?

如何编写仅在函数未引发预期异常的情况下失败的单元测试?

How does one write a unittest that fails only if a function doesn’t throw an expected exception?


回答 0

使用unittest模块中的TestCase.assertRaises(或TestCase.failUnlessRaises),例如:

import mymod

class MyTestCase(unittest.TestCase):
    def test1(self):
        self.assertRaises(SomeCoolException, mymod.myfunc)

Use TestCase.assertRaises (or TestCase.failUnlessRaises) from the unittest module, for example:

import mymod

class MyTestCase(unittest.TestCase):
    def test1(self):
        self.assertRaises(SomeCoolException, mymod.myfunc)

回答 1

从Python 2.7开始,您可以使用上下文管理器来获取抛出的实际Exception对象:

import unittest

def broken_function():
    raise Exception('This is broken')

class MyTestCase(unittest.TestCase):
    def test(self):
        with self.assertRaises(Exception) as context:
            broken_function()

        self.assertTrue('This is broken' in context.exception)

if __name__ == '__main__':
    unittest.main()

http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises


Python的3.5,你必须包装context.exceptionstr,否则,你会得到一个TypeError

self.assertTrue('This is broken' in str(context.exception))

Since Python 2.7 you can use context manager to get ahold of the actual Exception object thrown:

import unittest

def broken_function():
    raise Exception('This is broken')

class MyTestCase(unittest.TestCase):
    def test(self):
        with self.assertRaises(Exception) as context:
            broken_function()

        self.assertTrue('This is broken' in context.exception)

if __name__ == '__main__':
    unittest.main()

http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises


In Python 3.5, you have to wrap context.exception in str, otherwise you’ll get a TypeError

self.assertTrue('This is broken' in str(context.exception))

回答 2

我上一个答案中的代码可以简化为:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction)

如果函数接受参数,则将它们传递给assertRaises,如下所示:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction, arg1, arg2)

The code in my previous answer can be simplified to:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction)

And if afunction takes arguments, just pass them into assertRaises like this:

def test_afunction_throws_exception(self):
    self.assertRaises(ExpectedException, afunction, arg1, arg2)

回答 3

您如何测试Python函数引发异常?

如何编写仅在函数未引发预期异常的情况下失败的测试?

简短答案:

将该self.assertRaises方法用作上下文管理器:

    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'

示范

最佳实践方法相当容易在Python Shell中进行演示。

unittest

在Python 2.7或3中:

import unittest

在Python 2.6中,您可以安装2.7 unittest库的向后移植,称为unittest2,并将其别名为unittest

import unittest2 as unittest

测试示例

现在,将以下Python类型安全性测试粘贴到您的Python Shell中:

class MyTestCase(unittest.TestCase):
    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'
    def test_2_cannot_add_int_and_str(self):
        import operator
        self.assertRaises(TypeError, operator.add, 1, '1')

测试人员assertRaises用作上下文管理器,以确保在记录错误的同时正确捕获并清除该错误。

我们也可以使用上下文管理器来编写它,请参阅测试二。第一个参数是您希望引发的错误类型,第二个参数是您要测试的函数,其余的args和关键字args将传递给该函数。

我认为仅使用上下文管理器就更加简单,可读性和可维护性。

运行测试

要运行测试:

unittest.main(exit=False)

在Python 2.6中,您可能需要以下内容

unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

并且您的终端应输出以下内容:

..
----------------------------------------------------------------------
Ran 2 tests in 0.007s

OK
<unittest2.runner.TextTestResult run=2 errors=0 failures=0>

然后,正如我们期望的那样,尝试在中添加1'1'结果TypeError


有关更详细的输出,请尝试以下操作:

unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

How do you test that a Python function throws an exception?

How does one write a test that fails only if a function doesn’t throw an expected exception?

Short Answer:

Use the self.assertRaises method as a context manager:

    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'

Demonstration

The best practice approach is fairly easy to demonstrate in a Python shell.

The unittest library

In Python 2.7 or 3:

import unittest

In Python 2.6, you can install a backport of 2.7’s unittest library, called unittest2, and just alias that as unittest:

import unittest2 as unittest

Example tests

Now, paste into your Python shell the following test of Python’s type-safety:

class MyTestCase(unittest.TestCase):
    def test_1_cannot_add_int_and_str(self):
        with self.assertRaises(TypeError):
            1 + '1'
    def test_2_cannot_add_int_and_str(self):
        import operator
        self.assertRaises(TypeError, operator.add, 1, '1')

Test one uses assertRaises as a context manager, which ensures that the error is properly caught and cleaned up, while recorded.

We could also write it without the context manager, see test two. The first argument would be the error type you expect to raise, the second argument, the function you are testing, and the remaining args and keyword args will be passed to that function.

I think it’s far more simple, readable, and maintainable to just to use the context manager.

Running the tests

To run the tests:

unittest.main(exit=False)

In Python 2.6, you’ll probably need the following:

unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

And your terminal should output the following:

..
----------------------------------------------------------------------
Ran 2 tests in 0.007s

OK
<unittest2.runner.TextTestResult run=2 errors=0 failures=0>

And we see that as we expect, attempting to add a 1 and a '1' result in a TypeError.


For more verbose output, try this:

unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))

回答 4

您的代码应遵循以下模式(这是一个unittest模块样式测试):

def test_afunction_throws_exception(self):
    try:
        afunction()
    except ExpectedException:
        pass
    except Exception:
       self.fail('unexpected exception raised')
    else:
       self.fail('ExpectedException not raised')

在Python <2.7上,此构造对于检查预期异常中的特定值很有用。unittest函数assertRaises仅检查是否引发了异常。

Your code should follow this pattern (this is a unittest module style test):

def test_afunction_throws_exception(self):
    try:
        afunction()
    except ExpectedException:
        pass
    except Exception:
       self.fail('unexpected exception raised')
    else:
       self.fail('ExpectedException not raised')

On Python < 2.7 this construct is useful for checking for specific values in the expected exception. The unittest function assertRaises only checks if an exception was raised.


回答 5

来自:http : //www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/

首先,这是文件dum_function.py中相应的(still dum:p)函数:

def square_value(a):
   """
   Returns the square value of a.
   """
   try:
       out = a*a
   except TypeError:
       raise TypeError("Input should be a string:")

   return out

这是要执行的测试(仅插入此测试):

import dum_function as df # import function module
import unittest
class Test(unittest.TestCase):
   """
      The class inherits from unittest
      """
   def setUp(self):
       """
       This method is called before each test
       """
       self.false_int = "A"

   def tearDown(self):
       """
       This method is called after each test
       """
       pass
      #---
         ## TESTS
   def test_square_value(self):
       # assertRaises(excClass, callableObj) prototype
       self.assertRaises(TypeError, df.square_value(self.false_int))

   if __name__ == "__main__":
       unittest.main()

现在我们准备测试我们的功能!这是尝试运行测试时发生的情况:

======================================================================
ERROR: test_square_value (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_dum_function.py", line 22, in test_square_value
    self.assertRaises(TypeError, df.square_value(self.false_int))
  File "/home/jlengrand/Desktop/function.py", line 8, in square_value
    raise TypeError("Input should be a string:")
TypeError: Input should be a string:

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

TypeError被引发actullay,并生成测试失败。问题在于,这正是我们想要的行为:s。

为避免此错误,只需在测试调用中使用lambda运行该函数:

self.assertRaises(TypeError, lambda: df.square_value(self.false_int))

最终输出:

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

太好了!

…对我来说也是完美的!

非常感谢Julien Lengrand-Lambert先生


这个测试断言实际上返回一个假阳性。发生这种情况是因为’assertRaises’内部的lambda是引发类型错误而不是经过测试的函数的单位。

from: http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/

First, here is the corresponding (still dum :p) function in file dum_function.py :

def square_value(a):
   """
   Returns the square value of a.
   """
   try:
       out = a*a
   except TypeError:
       raise TypeError("Input should be a string:")

   return out

Here is the test to be performed (only this test is inserted):

import dum_function as df # import function module
import unittest
class Test(unittest.TestCase):
   """
      The class inherits from unittest
      """
   def setUp(self):
       """
       This method is called before each test
       """
       self.false_int = "A"

   def tearDown(self):
       """
       This method is called after each test
       """
       pass
      #---
         ## TESTS
   def test_square_value(self):
       # assertRaises(excClass, callableObj) prototype
       self.assertRaises(TypeError, df.square_value(self.false_int))

   if __name__ == "__main__":
       unittest.main()

We are now ready to test our function! Here is what happens when trying to run the test :

======================================================================
ERROR: test_square_value (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_dum_function.py", line 22, in test_square_value
    self.assertRaises(TypeError, df.square_value(self.false_int))
  File "/home/jlengrand/Desktop/function.py", line 8, in square_value
    raise TypeError("Input should be a string:")
TypeError: Input should be a string:

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

The TypeError is actullay raised, and generates a test failure. The problem is that this is exactly the behavior we wanted :s.

To avoid this error, simply run the function using lambda in the test call :

self.assertRaises(TypeError, lambda: df.square_value(self.false_int))

The final output :

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Perfect !

… and for me is perfect too!!

Thansk a lot Mr. Julien Lengrand-Lambert


This test assert actually returns a false positive. That happens because the lambda inside the ‘assertRaises’ is the unit that raises type error and not the tested function.


回答 6

您可以构建自己的程序contextmanager来检查是否引发了异常。

import contextlib

@contextlib.contextmanager
def raises(exception):
    try:
        yield 
    except exception as e:
        assert True
    else:
        assert False

然后您可以raises像这样使用:

with raises(Exception):
    print "Hola"  # Calls assert False

with raises(Exception):
    raise Exception  # Calls assert True

如果您使用pytest,则该东西已经实现。您可以pytest.raises(Exception)

例:

def test_div_zero():
    with pytest.raises(ZeroDivisionError):
        1/0

结果:

pigueiras@pigueiras$ py.test
================= test session starts =================
platform linux2 -- Python 2.6.6 -- py-1.4.20 -- pytest-2.5.2 -- /usr/bin/python
collected 1 items 

tests/test_div_zero.py:6: test_div_zero PASSED

You can build your own contextmanager to check if the exception was raised.

import contextlib

@contextlib.contextmanager
def raises(exception):
    try:
        yield 
    except exception as e:
        assert True
    else:
        assert False

And then you can use raises like this:

with raises(Exception):
    print "Hola"  # Calls assert False

with raises(Exception):
    raise Exception  # Calls assert True

If you are using pytest, this thing is implemented already. You can do pytest.raises(Exception):

Example:

def test_div_zero():
    with pytest.raises(ZeroDivisionError):
        1/0

And the result:

pigueiras@pigueiras$ py.test
================= test session starts =================
platform linux2 -- Python 2.6.6 -- py-1.4.20 -- pytest-2.5.2 -- /usr/bin/python
collected 1 items 

tests/test_div_zero.py:6: test_div_zero PASSED

回答 7

我几乎在所有地方都使用doctest [1],因为我喜欢同时记录和测试函数的事实。

看一下这段代码:

def throw_up(something, gowrong=False):
    """
    >>> throw_up('Fish n Chips')
    Traceback (most recent call last):
    ...
    Exception: Fish n Chips

    >>> throw_up('Fish n Chips', gowrong=True)
    'I feel fine!'
    """
    if gowrong:
        return "I feel fine!"
    raise Exception(something)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

如果将此示例放在模块中并从命令行运行它,则将评估并检查两个测试用例。

[1] Python文档:23.2 doctest-测试交互式Python示例

I use doctest[1] almost everywhere because I like the fact that I document and test my functions at the same time.

Have a look at this code:

def throw_up(something, gowrong=False):
    """
    >>> throw_up('Fish n Chips')
    Traceback (most recent call last):
    ...
    Exception: Fish n Chips

    >>> throw_up('Fish n Chips', gowrong=True)
    'I feel fine!'
    """
    if gowrong:
        return "I feel fine!"
    raise Exception(something)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

If you put this example in a module and run it from the command line both test cases are evaluated and checked.

[1] Python documentation: 23.2 doctest — Test interactive Python examples


回答 8

我刚刚发现,Mock库提供了assertRaisesWithMessage()方法(在其unittest.TestCase子类中),该方法不仅会检查是否引发了预期的异常,还检查了与预期消息一起引发的异常:

from testcase import TestCase

import mymod

class MyTestCase(TestCase):
    def test1(self):
        self.assertRaisesWithMessage(SomeCoolException,
                                     'expected message',
                                     mymod.myfunc)

I just discovered that the Mock library provides an assertRaisesWithMessage() method (in its unittest.TestCase subclass), which will check not only that the expected exception is raised, but also that it is raised with the expected message:

from testcase import TestCase

import mymod

class MyTestCase(TestCase):
    def test1(self):
        self.assertRaisesWithMessage(SomeCoolException,
                                     'expected message',
                                     mymod.myfunc)

回答 9

这里有很多答案。该代码显示了我们如何创建一个异常,如何在我们的方法中使用该异常,最后,您如何在单元测试中进行验证,并提出正确的异常。

import unittest

class DeviceException(Exception):
    def __init__(self, msg, code):
        self.msg = msg
        self.code = code
    def __str__(self):
        return repr("Error {}: {}".format(self.code, self.msg))

class MyDevice(object):
    def __init__(self):
        self.name = 'DefaultName'

    def setParameter(self, param, value):
        if isinstance(value, str):
            setattr(self, param , value)
        else:
            raise DeviceException('Incorrect type of argument passed. Name expects a string', 100001)

    def getParameter(self, param):
        return getattr(self, param)

class TestMyDevice(unittest.TestCase):

    def setUp(self):
        self.dev1 = MyDevice()

    def tearDown(self):
        del self.dev1

    def test_name(self):
        """ Test for valid input for name parameter """

        self.dev1.setParameter('name', 'MyDevice')
        name = self.dev1.getParameter('name')
        self.assertEqual(name, 'MyDevice')

    def test_invalid_name(self):
        """ Test to check if error is raised if invalid type of input is provided """

        self.assertRaises(DeviceException, self.dev1.setParameter, 'name', 1234)

    def test_exception_message(self):
        """ Test to check if correct exception message and code is raised when incorrect value is passed """

        with self.assertRaises(DeviceException) as cm:
            self.dev1.setParameter('name', 1234)
        self.assertEqual(cm.exception.msg, 'Incorrect type of argument passed. Name expects a string', 'mismatch in expected error message')
        self.assertEqual(cm.exception.code, 100001, 'mismatch in expected error code')


if __name__ == '__main__':
    unittest.main()

There are a lot of answers here. The code shows how we can create an Exception, how we can use that exception in our methods, and finally, how you can verify in a unit test, the correct exceptions being raised.

import unittest

class DeviceException(Exception):
    def __init__(self, msg, code):
        self.msg = msg
        self.code = code
    def __str__(self):
        return repr("Error {}: {}".format(self.code, self.msg))

class MyDevice(object):
    def __init__(self):
        self.name = 'DefaultName'

    def setParameter(self, param, value):
        if isinstance(value, str):
            setattr(self, param , value)
        else:
            raise DeviceException('Incorrect type of argument passed. Name expects a string', 100001)

    def getParameter(self, param):
        return getattr(self, param)

class TestMyDevice(unittest.TestCase):

    def setUp(self):
        self.dev1 = MyDevice()

    def tearDown(self):
        del self.dev1

    def test_name(self):
        """ Test for valid input for name parameter """

        self.dev1.setParameter('name', 'MyDevice')
        name = self.dev1.getParameter('name')
        self.assertEqual(name, 'MyDevice')

    def test_invalid_name(self):
        """ Test to check if error is raised if invalid type of input is provided """

        self.assertRaises(DeviceException, self.dev1.setParameter, 'name', 1234)

    def test_exception_message(self):
        """ Test to check if correct exception message and code is raised when incorrect value is passed """

        with self.assertRaises(DeviceException) as cm:
            self.dev1.setParameter('name', 1234)
        self.assertEqual(cm.exception.msg, 'Incorrect type of argument passed. Name expects a string', 'mismatch in expected error message')
        self.assertEqual(cm.exception.code, 100001, 'mismatch in expected error code')


if __name__ == '__main__':
    unittest.main()

回答 10

您可以使用unittest模块中的assertRaises

import unittest

class TestClass():
  def raises_exception(self):
    raise Exception("test")

class MyTestCase(unittest.TestCase):
  def test_if_method_raises_correct_exception(self):
    test_class = TestClass()
    # note that you dont use () when passing the method to assertRaises
    self.assertRaises(Exception, test_class.raises_exception)

You can use assertRaises from the unittest module

import unittest

class TestClass():
  def raises_exception(self):
    raise Exception("test")

class MyTestCase(unittest.TestCase):
  def test_if_method_raises_correct_exception(self):
    test_class = TestClass()
    # note that you dont use () when passing the method to assertRaises
    self.assertRaises(Exception, test_class.raises_exception)

回答 11

尽管所有答案都很好,但我仍在寻找一种方法来测试函数是否引发异常,而无需依赖于单元测试框架和编写测试类。

我最终写了以下内容:

def assert_error(e, x):
    try:
        e(x)
    except:
        return
    raise AssertionError()

def failing_function(x):
    raise ValueError()

def dummy_function(x):
    return x

if __name__=="__main__":
    assert_error(failing_function, 0)
    assert_error(dummy_function, 0)

它在正确的行失败:

Traceback (most recent call last):
  File "assert_error.py", line 16, in <module>
    assert_error(dummy_function, 0)
  File "assert_error.py", line 6, in assert_error
    raise AssertionError()
AssertionError

While all the answers are perfectly fine, I was looking for a way to test if a function raised an exception without relying on unit testing frameworks and having to write test classes.

I ended up writing the following:

def assert_error(e, x):
    try:
        e(x)
    except:
        return
    raise AssertionError()

def failing_function(x):
    raise ValueError()

def dummy_function(x):
    return x

if __name__=="__main__":
    assert_error(failing_function, 0)
    assert_error(dummy_function, 0)

And it fails on the right line :

Traceback (most recent call last):
  File "assert_error.py", line 16, in <module>
    assert_error(dummy_function, 0)
  File "assert_error.py", line 6, in assert_error
    raise AssertionError()
AssertionError