标签归档:Python

如何检查Django版本

问题:如何检查Django版本

我必须为我们的应用程序使用PythonDjango。所以我有两个版本的Python,分别是2.6和2.7。现在,我已经安装了Django。我可以运行示例应用程序以测试Django成功。但是,如何确定Django使用2.6还是2.7版本以及Django使用什么版本的模块?

I have to use Python and Django for our application. So I have two versions of Python, 2.6 and 2.7. Now I have installed Django. I could run the sample application for testing Django succesfuly. But how do I make sure whether Django uses the 2.6 or 2.7 version and what version of modules Django uses?


回答 0

Django 1.5支持Python 2.6.5和更高版本。

如果您使用的是Linux,并且要检查使用的Python版本,请从命令行运行python -V

如果要检查Django版本,请打开Python控制台并输入

>>> import django
>>> django.VERSION
(2, 0, 0, 'final', 0)

Django 1.5 supports Python 2.6.5 and later.

If you’re under Linux and want to check the Python version you’re using, run python -V from the command line.

If you want to check the Django version, open a Python console and type

>>> import django
>>> django.VERSION
(2, 0, 0, 'final', 0)

回答 1

基本上与bcoughlan的答案相同,但是在这里,它作为可执行命令:

$ python -c "import django; print(django.get_version())"
2.0

Basically the same as bcoughlan’s answer, but here it is as an executable command:

$ python -c "import django; print(django.get_version())"
2.0

回答 2

如果您已安装该应用程序:

$ django-admin.py version
2.0

If you have installed the application:

$ django-admin.py version
2.0

回答 3

转到Django项目主目录并执行以下操作:

./manage.py --version

Go to your Django project home directory and do:

./manage.py --version

回答 4

>>> import django
>>> print(django.get_version())
1.6.1

我正在使用IDLE(Python GUI)。

>>> import django
>>> print(django.get_version())
1.6.1

I am using the IDLE (Python GUI).


回答 5

如果您有点子,也可以

点冻结
它将显示您的所有组件版本,包括Django。

您可以通过grep传递它,以仅获取Django版本。那是,

josh@villaroyale:~/code/djangosite$ pip freeze | grep Django
Django==1.4.3

If you have pip, you can also do a

pip freeze
and it will show your all component version including Django .

You can pipe it through grep to get just the Django version. That is,

josh@villaroyale:~/code/djangosite$ pip freeze | grep Django
Django==1.4.3

回答 6

对于Python

import sys
sys.version

对于Django(如其他人在此处所述):

import django
django.get_version()

仅检查版本的潜在问题是版本会升级,因此代码可能会过时。您要确保’1.7′<‘1.7.1′<‘1.7.5′<‘1.7.10’。普通的字符串比较将在最后一次比较中失败:

>>> '1.7.5' < '1.7.10'
False

解决方案是使用distutils中的StrictVersion

>>> from distutils.version import StrictVersion
>>> StrictVersion('1.7.5') < StrictVersion('1.7.10')
True

For Python:

import sys
sys.version

For Django (as mentioned by others here):

import django
django.get_version()

The potential problem with simply checking the version, is that versions get upgraded and so the code can go out of date. You want to make sure that ‘1.7’ < ‘1.7.1’ < ‘1.7.5’ < ‘1.7.10’. A normal string comparison would fail in the last comparison:

>>> '1.7.5' < '1.7.10'
False

The solution is to use StrictVersion from distutils.

>>> from distutils.version import StrictVersion
>>> StrictVersion('1.7.5') < StrictVersion('1.7.10')
True

回答 7

正如您所说的,您有两个版本的python,我假设它们位于不同的虚拟环境(例如venv)或conda 环境中

当您安装django时,可能仅在一种环境中。可能有两个不同版本的django,每个版本的python都有一个。

在Unix / Mac终端中,您可以如下检查python版本:

$ python --version

如果您想知道来源:

$ which python

并检查django的版本:

$ python -m django --version

As you say you have two versions of python, I assume they are in different virtual environments (e.g. venv) or perhaps conda environments.

When you installed django, it was likely in only one environment. It is possible that you have two different versions of django, one for each version of python.

In from a Unix/Mac terminal, you can check your python version as follows:

$ python --version

If you want to know the source:

$ which python

And to check the version of django:

$ python -m django --version

回答 8

有多种获取Django版本的方法。您可以根据需要使用以下给出的任何一种。

注意: 如果您在虚拟环境中工作,请加载python环境


终端命令

  1. python -m django --version
  2. django-admin --version 要么 django-admin.py version
  3. ./manage.py --version 要么 python manage.py --version
  4. pip freeze | grep Django
  5. python -c "import django; print(django.get_version())"
  6. python manage.py runserver --version

Django Shell命令

  1. import django django.get_version() 要么 django.VERSION
  2. from django.utils import version version.get_version() 要么 version.get_complete_version()
  3. import pkg_resources pkg_resources.get_distribution('django').version

(如果您有某种更正或想添加更多相关信息,请随意修改此答案。)

There are various ways to get the Django version. You can use any one of the following given below according to your requirements.

Note: If you are working in a virtual environment then please load your python environment


Terminal Commands

  1. python -m django --version
  2. django-admin --version or django-admin.py version
  3. ./manage.py --version or python manage.py --version
  4. pip freeze | grep Django
  5. python -c "import django; print(django.get_version())"
  6. python manage.py runserver --version

Django Shell Commands

  1. import django django.get_version() OR django.VERSION
  2. from django.utils import version version.get_version() OR version.get_complete_version()
  3. import pkg_resources pkg_resources.get_distribution('django').version

(Feel free to modify this answer, if you have some kind of correction or you want to add more related information.)


回答 9

要使用Python Shell进行检查,请执行以下操作。

>>>from django import get_version
>>> get_version()

如果您希望在Unix / Linux shell中使用一行来完成此操作,请执行

python -c 'import django; print(django.get_version())'

开发应用程序后,即可使用以下方法直接检查版本。

python manage.py runserver --version

For checking using a Python shell, do the following.

>>>from django import get_version
>>> get_version()

If you wish to do it in Unix/Linux shell with a single line, then do

python -c 'import django; print(django.get_version())'

Once you have developed an application, then you can check version directly using the following.

python manage.py runserver --version

回答 10

django-admin --version
python manage.py --version
pip freeze | grep django
django-admin --version
python manage.py --version
pip freeze | grep django

回答 11

Django将使用PYTHONPATH环境变量指定的Python版本。您可以echo $PYTHONPATH在外壳中使用以确定要使用的版本。

Django使用的模块版本将是PYTHONPATH指定的Python版本下安装的模块版本。

Django will use the version of Python specified by the PYTHONPATH environment variable. You can use echo $PYTHONPATH in a shell to determine which version will be used.

The module versions used by Django will be the module versions installed under the version of Python specified by PYTHONPATH.


回答 12

pip list在LINUX TERMINAL上运行,并在列表中找到Django及其版本

pip freeze在Windows上的cmd上 运行

run pip list on LINUX TERMINAL and find Django and its version on list

run pip freeze on cmd on Windows


回答 13

您也可以不用Python就可以做到。只需在Django目录中输入以下内容即可:

cat __init__.py | grep VERSION

你会得到类似的东西:

VERSION = (1, 5, 5, 'final', 0)

You can do it without Python too. Just type this in your Django directory:

cat __init__.py | grep VERSION

And you will get something like:

VERSION = (1, 5, 5, 'final', 0)

回答 14

Django中有一个未记录的utils版本模块

https://github.com/django/django/blob/master/django/utils/version.py

有了它,您可以将正常版本作为字符串或详细版本元组获取:

>>> from django.utils import version
>>> version.get_version()
... 1.9
>>> version.get_complete_version()
... (1, 9, 0, 'final', 0)

There is an undocumented utils versions module in django

https://github.com/django/django/blob/master/django/utils/version.py

With that you can get the normal version as string or a detailed version tuple:

>>> from django.utils import version
>>> version.get_version()
... 1.9
>>> version.get_complete_version()
... (1, 9, 0, 'final', 0)

回答 15

Django版本或任何其他软件包版本

打开终端或命令提示符

类型

pip show django

要么

pip3 show django

您可以找到任何软件包版本…
示例

pip show tensorflow

pip show numpy 

等等….

Django version or any other package version

open the terminal or command prompt

type

pip show django

or

pip3 show django

you can find any package version…
example

pip show tensorflow

pip show numpy 

etc….


回答 16

输入您的CMD或终端:

python -m django --version

Type in your CMD or terminal:

python -m django --version

回答 17

我认为最Python化的方式是:

>>> import pkg_resources; 
>>> pkg_resources.get_distribution('django').version
'1.8.4'

这直接与setup.py相关联: https //github.com/django/django/blob/master/setup.py#L37

这绝对是获得ANY软件包版本号的最佳方法!

也有 distutils

>>> from distutils.version import LooseVersion, StrictVersion
>>> LooseVersion("2.3.1") < LooseVersion("10.1.2")
True
>>> StrictVersion("2.3.1") < StrictVersion("10.1.2")
True
>>> StrictVersion("2.3.1") > StrictVersion("10.1.2")
False

至于python版本,我同意@jamesdradbury

>>> import sys
>>> sys.version
'3.4.3 (default, Jul 13 2015, 12:18:23) \n[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)]'

捆绑在一起:

>>> StrictVersion((sys.version.split(' ')[0])) > StrictVersion('2.6')
True

I thought the most pythonic way was:

>>> import pkg_resources; 
>>> pkg_resources.get_distribution('django').version
'1.8.4'

This ties directly into setup.py: https://github.com/django/django/blob/master/setup.py#L37

Its definitely the best way to get the version number of ANY package!

Also there is distutils

>>> from distutils.version import LooseVersion, StrictVersion
>>> LooseVersion("2.3.1") < LooseVersion("10.1.2")
True
>>> StrictVersion("2.3.1") < StrictVersion("10.1.2")
True
>>> StrictVersion("2.3.1") > StrictVersion("10.1.2")
False

As for the python version, i agree with @jamesdradbury

>>> import sys
>>> sys.version
'3.4.3 (default, Jul 13 2015, 12:18:23) \n[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)]'

Tying it all together:

>>> StrictVersion((sys.version.split(' ')[0])) > StrictVersion('2.6')
True

回答 18

如果要进行Django版本比较,可以使用django-nine(pip install django-nine)。例如,如果您的环境中安装的Django版本是1.7.4,则以下内容将适用。

from nine import versions

versions.DJANGO_1_7 # True
versions.DJANGO_LTE_1_7 # True
versions.DJANGO_GTE_1_7 # True
versions.DJANGO_GTE_1_8 # False
versions.DJANGO_GTE_1_4 # True
versions.DJANGO_LTE_1_6 # False

If you want to make Django version comparison, you could use django-nine (pip install django-nine). For example, if Django version installed in your environment is 1.7.4, then the following would be true.

from nine import versions

versions.DJANGO_1_7 # True
versions.DJANGO_LTE_1_7 # True
versions.DJANGO_GTE_1_7 # True
versions.DJANGO_GTE_1_8 # False
versions.DJANGO_GTE_1_4 # True
versions.DJANGO_LTE_1_6 # False

回答 19

在Python Shell中输入以下命令

import django
django.get_version()

Type the following command in Python shell

import django
django.get_version()

回答 20

Django 1.0之后,您可以执行此操作

$ django-admin --version
1.11.10

After django 1.0 you can just do this

$ django-admin --version
1.11.10

回答 21

您可以通过在shell提示符中运行以下命令来获取Django版本

python -m django –version

如果安装了Django,则应该看到该版本,否则将收到错误消息,提示“没有名为django的模块”。

You can get django version by running the following command in a shell prompt

python -m django –version

If Django is installed, you should see the version otherwise you’ll get an error telling “No module named django”.


回答 22

您可以导入django,然后按如下所示键入print语句,以了解django的版本,即安装在系统上的版本:

>>> import django
>>> print(django.get_version())
2.1

you can import django and then type print statement as given below to know the version of django i.e. installed on your system:

>>> import django
>>> print(django.get_version())
2.1

回答 23

Django版本支持的Python版本

Django version     Python versions
1.0                2.3, 2.4, 2.5, 2.6
1.1                2.3, 2.4, 2.5, 2.6
1.2                2.4, 2.5, 2.6, 2.7
1.3                2.4, 2.5, 2.6, 2.7
1.4                2.5, 2.6, 2.7
1.5                2.6.5, 2.7 and 3.2.3, 3.3 (experimental)
1.6                2.6.5, 2.7 and 3.2.3, 3.3
1.11               2.7, 3.4, 3.5, 3.6, 3.7 (added in 1.11.17)
2.0                3.4, 3.5, 3.6, 3.7
2.1, 2.2           3.5, 3.6, 3.7

要验证Python是否可以看到Django,请在您的shell中键入python。然后在Python提示符下,尝试导入Django:

>>> import django
>>> print(django.get_version())
2.1
>>> django.VERSION
(2, 1, 4, 'final', 0)

Python version supported by Django version

Django version     Python versions
1.0                2.3, 2.4, 2.5, 2.6
1.1                2.3, 2.4, 2.5, 2.6
1.2                2.4, 2.5, 2.6, 2.7
1.3                2.4, 2.5, 2.6, 2.7
1.4                2.5, 2.6, 2.7
1.5                2.6.5, 2.7 and 3.2.3, 3.3 (experimental)
1.6                2.6.5, 2.7 and 3.2.3, 3.3
1.11               2.7, 3.4, 3.5, 3.6, 3.7 (added in 1.11.17)
2.0                3.4, 3.5, 3.6, 3.7
2.1, 2.2           3.5, 3.6, 3.7

To verify that Django can be seen by Python, type python from your shell. Then at the Python prompt, try to import Django:

>>> import django
>>> print(django.get_version())
2.1
>>> django.VERSION
(2, 1, 4, 'final', 0)

回答 24

只需键入python -m django --version 或键入pip freeze即可查看已安装模块的所有版本,包括Django。

Simply type python -m django --version or type pip freeze to see all the versions of installed modules including Django.


使用Python的stdlib查找本地IP地址

问题:使用Python的stdlib查找本地IP地址

如何仅使用标准库在Python平台中独立查找本地IP地址(即192.168.xx或10.0.xx)?

How can I find local IP addresses (i.e. 192.168.x.x or 10.0.x.x) in Python platform independently and using only the standard library?


回答 0

import socket
socket.gethostbyname(socket.gethostname())

这将永远无法正常工作(返回127.0.0.1主机/etc/hosts名为as的机器127.0.0.1),将是gimel显示的一种称呼,socket.getfqdn()而是使用。当然,您的计算机需要一个可解析的主机名。

import socket
socket.gethostbyname(socket.gethostname())

This won’t work always (returns 127.0.0.1 on machines having the hostname in /etc/hosts as 127.0.0.1), a paliative would be what gimel shows, use socket.getfqdn() instead. Of course your machine needs a resolvable hostname.


回答 1

我刚刚发现了它,但是似乎有点破烂,但是他们说在* nix上尝试过,而我在Windows上做了,它起作用了。

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()

这假设您可以访问互联网,并且没有本地代理。

I just found this but it seems a bit hackish, however they say tried it on *nix and I did on windows and it worked.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()

This assumes you have an internet access, and that there is no local proxy.


回答 2

此方法在本地设备(具有默认路由的设备)上返回“主要” IP

  • 完全不需要可路由的网络访问或任何连接。
  • 即使所有接口都从网络上拔下,它也可以工作。
  • 不需要甚至尝试到达其他任何地方
  • 与NAT,公共IP,专用IP,外部IP和内部IP一起使用
  • 没有外部依赖项的纯Python 2(或3)。
  • 适用于Linux,Windows和OSX。

Python 3或2:

import socket
def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except Exception:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

这将返回一个作为主IP的IP(具有默认路由的IP)。如果您需要将所有IP附加到所有接口(包括localhost等),请参阅此答案

如果您像家庭中的wifi盒一样位于NAT防火墙的后面,则不会显示您的公共NAT IP,而是显示您本地IP上的私有IP,该IP具有到您本地WIFI路由器的默认路由;获取您的wifi路由器的外部IP要么需要在THAT盒子上运行它,要么连接到可能反映IP的外部服务,例如whatismyip.com/whatismyipaddress.com …,但这与原始问题完全不同。:)

This method returns the “primary” IP on the local box (the one with a default route).

  • Does NOT need routable net access or any connection at all.
  • Works even if all interfaces are unplugged from the network.
  • Does NOT need or even try to get anywhere else.
  • Works with NAT, public, private, external, and internal IP’s
  • Pure Python 2 (or 3) with no external dependencies.
  • Works on Linux, Windows, and OSX.

Python 3 or 2:

import socket
def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except Exception:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

This returns a single IP which is the primary (the one with a default route). If you need instead all IP’s attached to all interfaces (including localhost, etc), see this answer.

If you are behind a NAT firewall like your wifi box at home, then this will not show your public NAT IP, but instead your private IP on the local network which has a default route to your local WIFI router; getting your wifi router’s external IP would either require running this on THAT box, or connecting to an external service such as whatismyip.com/whatismyipaddress.com that could reflect back the IP… but that is completely different from the original question. :)


回答 3

作为别名myip,应该在任何地方都有效:

alias myip="python -c 'import socket; print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith(\"127.\")][:1], [[(s.connect((\"8.8.8.8\", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])'"
  • 可与Python 2.x,Python 3.x,现代和旧版Linux发行版,OSX / macOS和Windows一起正常使用,以查找当前的IPv4地址。
  • 对于具有多个IP地址,IPv6,没有配置的IP地址或没有Internet访问的计算机,不会返回正确的结果。

与上述相同,但只有Python代码:

import socket
print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])
  • 如果未配置IP地址,这将引发异常。

在没有Internet连接的情况下也可以在LAN上运行的版本:

import socket
print((([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) + ["no IP found"])[0])

(感谢@ccpizza


背景

使用socket.gethostbyname(socket.gethostname())在这里不起作用,因为我所在的其中一台计算机上有/etc/hosts重复的条目并对其自身进行了引用。socket.gethostbyname()仅返回中的最后一项/etc/hosts

这是我最初的尝试,清除了所有以以下地址开头的地址"127."

import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])

这适用于Linux 2和Windows上的Python 2和3,但不适用于多个网络设备或IPv6。但是,它停止了在最近的Linux发行版上的工作,因此我尝试了这种替代技术。它尝试通过8.8.8.8以下端口连接到Google DNS服务器53

import socket
print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])

然后,我将上述两种技术组合成一种在任何地方都可以使用的单行myip代码,并在此答案的顶部创建了别名和Python代码段。

随着IPv6的日益普及以及对于具有多个网络接口的服务器,使用第三方Python模块查找IP地址可能比此处列出的任何方法都更可靠和可靠。

As an alias called myip, that should work everywhere:

alias myip="python -c 'import socket; print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith(\"127.\")][:1], [[(s.connect((\"8.8.8.8\", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])'"
  • Works correctly with Python 2.x, Python 3.x, modern and old Linux distros, OSX/macOS and Windows for finding the current IPv4 address.
  • Will not return the correct result for machines with multiple IP addresses, IPv6, no configured IP address or no internet access.

Same as above, but only the Python code:

import socket
print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])
  • This will throw an exception if no IP address is configured.

Version that will also work on LANs without an internet connection:

import socket
print((([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) + ["no IP found"])[0])

(thanks @ccpizza)


Background:

Using socket.gethostbyname(socket.gethostname()) did not work here, because one of the computers I was on had an /etc/hosts with duplicate entries and references to itself. socket.gethostbyname() only returns the last entry in /etc/hosts.

This was my initial attempt, which weeds out all addresses starting with "127.":

import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])

This works with Python 2 and 3, on Linux and Windows, but does not deal with several network devices or IPv6. However, it stopped working on recent Linux distros, so I tried this alternative technique instead. It tries to connect to the Google DNS server at 8.8.8.8 at port 53:

import socket
print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])

Then I combined the two above techniques into a one-liner that should work everywhere, and created the myip alias and Python snippet at the top of this answer.

With the increasing popularity of IPv6, and for servers with multiple network interfaces, using a third-party Python module for finding the IP address is probably both more robust and reliable than any of the methods listed here.


回答 4

您可以使用netifaces模块。只需输入:

pip install netifaces

在命令外壳中,它将在默认的Python安装中自行安装。

然后,您可以像这样使用它:

from netifaces import interfaces, ifaddresses, AF_INET
for ifaceName in interfaces():
    addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
    print '%s: %s' % (ifaceName, ', '.join(addresses))

在我的计算机上打印:

{45639BDC-1050-46E0-9BE9-075C30DE1FBC}:192.168.0.100
{D43A468B-F3AE-4BF9-9391-4863A4500583} :: 10.5.9.207

该模块的作者声称它应该可以在Windows,UNIX和Mac OS X上运行。

You can use the netifaces module. Just type:

pip install netifaces

in your command shell and it will install itself on default Python installation.

Then you can use it like this:

from netifaces import interfaces, ifaddresses, AF_INET
for ifaceName in interfaces():
    addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
    print '%s: %s' % (ifaceName, ', '.join(addresses))

On my computer it printed:

{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100
{D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207

Author of this module claims it should work on Windows, UNIX and Mac OS X.


回答 5

套接字API方法

参见https://stackoverflow.com/a/28950776/711085

缺点:

  • 不是跨平台的。
  • 需要更多后备代码,与互联网上特定地址的存在相关
  • 如果您在使用NAT,这也将不起作用
  • 可能会创建UDP连接,而不依赖于(通常是ISP的)DNS可用性(请参阅其他答案,以获取使用8.8.8.8的想法:Google的(偶然也是DNS)服务器)
  • 确保将目标地址设置为UNREACHABLE,例如指定不使用的数字IP地址。请勿使用诸如fakesubdomain.google.com或somefakewebsite.com之类的域;您仍然会向该方发送垃圾邮件(无论现在还是将来),并在此过程中向您自己的网络邮箱发送垃圾邮件。

反射法

(请注意,这不能回答OP的本地IP地址问题,例如192.168 …;它为您提供了公共IP地址,根据使用情况,可能更需要此IP地址。)

您可以查询某些网站,例如whatismyip.com(但使用API​​),例如:

from urllib.request import urlopen
import re
def getPublicIp():
    data = str(urlopen('http://checkip.dyndns.com/').read())
    # data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'

    return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)

或者如果使用python2:

from urllib import urlopen
import re
def getPublicIp():
    data = str(urlopen('http://checkip.dyndns.com/').read())
    # data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'

    return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)

优点:

  • 这种方法的一个好处是它是跨平台的
  • 它可以从丑陋的NAT(例如您的家庭路由器)后面运行。

缺点(和解决方法):

  • 要求此网站正常运行,格式不得更改(几乎肯定不会更改),并且您的DNS服务器正常工作。如果发生故障,还可以通过查询其他第三方IP地址反射器来缓解此问题。
  • 如果您不查询多个反射器(以防止受损的反射器告诉您您的地址不是它的东西),或者如果您不使用HTTPS(以防止中间人的攻击),则可能是攻击向量成为服务器)

编辑:尽管起初我以为这些方法确实很糟糕(除非您使用了许多后备功能,否则从现在起很多年后代码都将是无关紧要的),但确实提出了“什么是互联网?”的问题。一台计算机可能具有指向许多不同网络的许多接口。有关主题的更详尽说明,请使用googlegateways and routes。计算机可能能够通过内部网关访问内部网络,或者通过例如路由器上的网关访问万维网(通常是这种情况)。OP询问的本地IP地址仅在单个链路层上定义明确,因此您必须指定(“我们正在谈论的是网卡还是以太网电缆?”) 。提出的这个问题可能有多个非唯一答案。但是,万维网上的全局IP地址可能是定义明确的(在没有大量网络碎片的情况下):可能是通过可以访问TLD的网关返回的路径。

Socket API method

see https://stackoverflow.com/a/28950776/711085

Downsides:

  • Not cross-platform.
  • Requires more fallback code, tied to existence of particular addresses on the internet
  • This will also not work if you’re behind a NAT
  • Probably creates a UDP connection, not independent of (usually ISP’s) DNS availability (see other answers for ideas like using 8.8.8.8: Google’s (coincidentally also DNS) server)
  • Make sure you make the destination address UNREACHABLE, like a numeric IP address that is spec-guaranteed to be unused. Do NOT use some domain like fakesubdomain.google.com or somefakewebsite.com; you’ll still be spamming that party (now or in the future), and spamming your own network boxes as well in the process.

Reflector method

(Do note that this does not answer the OP’s question of the local IP address, e.g. 192.168…; it gives you your public IP address, which might be more desirable depending on use case.)

You can query some site like whatismyip.com (but with an API), such as:

from urllib.request import urlopen
import re
def getPublicIp():
    data = str(urlopen('http://checkip.dyndns.com/').read())
    # data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'

    return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)

or if using python2:

from urllib import urlopen
import re
def getPublicIp():
    data = str(urlopen('http://checkip.dyndns.com/').read())
    # data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'

    return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)

Advantages:

  • One upside of this method is it’s cross-platform
  • It works from behind ugly NATs (e.g. your home router).

Disadvantages (and workarounds):

  • Requires this website to be up, the format to not change (almost certainly won’t), and your DNS servers to be working. One can mitigate this issue by also querying other third-party IP address reflectors in case of failure.
  • Possible attack vector if you don’t query multiple reflectors (to prevent a compromised reflector from telling you that your address is something it’s not), or if you don’t use HTTPS (to prevent a man-in-the-middle attack pretending to be the server)

edit: Though initially I thought these methods were really bad (unless you use many fallbacks, the code may be irrelevant many years from now), it does pose the question “what is the internet?”. A computer may have many interfaces pointing to many different networks. For a more thorough description of the topic, google for gateways and routes. A computer may be able to access an internal network via an internal gateway, or access the world-wide web via a gateway on for example a router (usually the case). The local IP address that the OP asks about is only well-defined with respect to a single link layer, so you have to specify that (“is it the network card, or the ethernet cable, which we’re talking about?”). There may be multiple non-unique answers to this question as posed. However the global IP address on the world-wide web is probably well-defined (in the absence of massive network fragmentation): probably the return path via the gateway which can access the TLDs.


回答 6

如果计算机具有通往Internet的路由,即使/ etc / hosts设置不正确,它始终可以获取首选的本地ip地址。

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 1))  # connect() for UDP doesn't send packets
local_ip_address = s.getsockname()[0]

If the computer has a route to the Internet, this will always work to get the preferred local ip address, even if /etc/hosts is not set correctly.

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 1))  # connect() for UDP doesn't send packets
local_ip_address = s.getsockname()[0]

回答 7

在Linux上:

>>> import socket, struct, fcntl
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sockfd = sock.fileno()
>>> SIOCGIFADDR = 0x8915
>>>
>>> def get_ip(iface = 'eth0'):
...     ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
...     try:
...         res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
...     except:
...         return None
...     ip = struct.unpack('16sH2x4s8x', res)[2]
...     return socket.inet_ntoa(ip)
... 
>>> get_ip('eth0')
'10.80.40.234'
>>> 

On Linux:

>>> import socket, struct, fcntl
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sockfd = sock.fileno()
>>> SIOCGIFADDR = 0x8915
>>>
>>> def get_ip(iface = 'eth0'):
...     ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
...     try:
...         res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
...     except:
...         return None
...     ip = struct.unpack('16sH2x4s8x', res)[2]
...     return socket.inet_ntoa(ip)
... 
>>> get_ip('eth0')
'10.80.40.234'
>>> 

回答 8

即时通讯使用以下模块:

#!/usr/bin/python
# module for getting the lan ip address of the computer

import os
import socket

if os.name != "nt":
    import fcntl
    import struct
    def get_interface_ip(ifname):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        return socket.inet_ntoa(fcntl.ioctl(
                s.fileno(),
                0x8915,  # SIOCGIFADDR
                struct.pack('256s', bytes(ifname[:15], 'utf-8'))
                # Python 2.7: remove the second argument for the bytes call
            )[20:24])

def get_lan_ip():
    ip = socket.gethostbyname(socket.gethostname())
    if ip.startswith("127.") and os.name != "nt":
        interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
        for ifname in interfaces:
            try:
                ip = get_interface_ip(ifname)
                break;
            except IOError:
                pass
    return ip

经过Windows和Linux(并不需要其他模块)测试,旨在用于基于单个IPv4的LAN中的系统。

接口名称的固定列表不适用于最新的Linux版本,这些版本采用了Alexander指出的有关可预测接口名称的systemd v197更改。在这种情况下,您需要使用系统上的接口名称手动替换列表,或使用其他解决方案(如netifaces)

im using following module:

#!/usr/bin/python
# module for getting the lan ip address of the computer

import os
import socket

if os.name != "nt":
    import fcntl
    import struct
    def get_interface_ip(ifname):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        return socket.inet_ntoa(fcntl.ioctl(
                s.fileno(),
                0x8915,  # SIOCGIFADDR
                struct.pack('256s', bytes(ifname[:15], 'utf-8'))
                # Python 2.7: remove the second argument for the bytes call
            )[20:24])

def get_lan_ip():
    ip = socket.gethostbyname(socket.gethostname())
    if ip.startswith("127.") and os.name != "nt":
        interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
        for ifname in interfaces:
            try:
                ip = get_interface_ip(ifname)
                break;
            except IOError:
                pass
    return ip

Tested with windows and linux (and doesnt require additional modules for those) intended for use on systems which are in a single IPv4 based LAN.

The fixed list of interface names does not work for recent linux versions, which have adopted the systemd v197 change regarding predictable interface names as pointed out by Alexander. In such cases, you need to manually replace the list with the interface names on your system, or use another solution like netifaces.


回答 9

我在我的ubuntu机器上使用它:

import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]

这行不通。

I use this on my ubuntu machines:

import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]

This doesn’t work.


回答 10

如果您不想使用外部软件包,也不想依赖外部Internet服务器,则可能会有所帮助。这是我在Google代码搜索中找到并修改为返回所需信息的代码示例:

def getIPAddresses():
    from ctypes import Structure, windll, sizeof
    from ctypes import POINTER, byref
    from ctypes import c_ulong, c_uint, c_ubyte, c_char
    MAX_ADAPTER_DESCRIPTION_LENGTH = 128
    MAX_ADAPTER_NAME_LENGTH = 256
    MAX_ADAPTER_ADDRESS_LENGTH = 8
    class IP_ADDR_STRING(Structure):
        pass
    LP_IP_ADDR_STRING = POINTER(IP_ADDR_STRING)
    IP_ADDR_STRING._fields_ = [
        ("next", LP_IP_ADDR_STRING),
        ("ipAddress", c_char * 16),
        ("ipMask", c_char * 16),
        ("context", c_ulong)]
    class IP_ADAPTER_INFO (Structure):
        pass
    LP_IP_ADAPTER_INFO = POINTER(IP_ADAPTER_INFO)
    IP_ADAPTER_INFO._fields_ = [
        ("next", LP_IP_ADAPTER_INFO),
        ("comboIndex", c_ulong),
        ("adapterName", c_char * (MAX_ADAPTER_NAME_LENGTH + 4)),
        ("description", c_char * (MAX_ADAPTER_DESCRIPTION_LENGTH + 4)),
        ("addressLength", c_uint),
        ("address", c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH),
        ("index", c_ulong),
        ("type", c_uint),
        ("dhcpEnabled", c_uint),
        ("currentIpAddress", LP_IP_ADDR_STRING),
        ("ipAddressList", IP_ADDR_STRING),
        ("gatewayList", IP_ADDR_STRING),
        ("dhcpServer", IP_ADDR_STRING),
        ("haveWins", c_uint),
        ("primaryWinsServer", IP_ADDR_STRING),
        ("secondaryWinsServer", IP_ADDR_STRING),
        ("leaseObtained", c_ulong),
        ("leaseExpires", c_ulong)]
    GetAdaptersInfo = windll.iphlpapi.GetAdaptersInfo
    GetAdaptersInfo.restype = c_ulong
    GetAdaptersInfo.argtypes = [LP_IP_ADAPTER_INFO, POINTER(c_ulong)]
    adapterList = (IP_ADAPTER_INFO * 10)()
    buflen = c_ulong(sizeof(adapterList))
    rc = GetAdaptersInfo(byref(adapterList[0]), byref(buflen))
    if rc == 0:
        for a in adapterList:
            adNode = a.ipAddressList
            while True:
                ipAddr = adNode.ipAddress
                if ipAddr:
                    yield ipAddr
                adNode = adNode.next
                if not adNode:
                    break

用法:

>>> for addr in getIPAddresses():
>>>    print addr
192.168.0.100
10.5.9.207

由于它依赖windll,因此仅在Windows上有效。

If you don’t want to use external packages and don’t want to rely on outside Internet servers, this might help. It’s a code sample that I found on Google Code Search and modified to return required information:

def getIPAddresses():
    from ctypes import Structure, windll, sizeof
    from ctypes import POINTER, byref
    from ctypes import c_ulong, c_uint, c_ubyte, c_char
    MAX_ADAPTER_DESCRIPTION_LENGTH = 128
    MAX_ADAPTER_NAME_LENGTH = 256
    MAX_ADAPTER_ADDRESS_LENGTH = 8
    class IP_ADDR_STRING(Structure):
        pass
    LP_IP_ADDR_STRING = POINTER(IP_ADDR_STRING)
    IP_ADDR_STRING._fields_ = [
        ("next", LP_IP_ADDR_STRING),
        ("ipAddress", c_char * 16),
        ("ipMask", c_char * 16),
        ("context", c_ulong)]
    class IP_ADAPTER_INFO (Structure):
        pass
    LP_IP_ADAPTER_INFO = POINTER(IP_ADAPTER_INFO)
    IP_ADAPTER_INFO._fields_ = [
        ("next", LP_IP_ADAPTER_INFO),
        ("comboIndex", c_ulong),
        ("adapterName", c_char * (MAX_ADAPTER_NAME_LENGTH + 4)),
        ("description", c_char * (MAX_ADAPTER_DESCRIPTION_LENGTH + 4)),
        ("addressLength", c_uint),
        ("address", c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH),
        ("index", c_ulong),
        ("type", c_uint),
        ("dhcpEnabled", c_uint),
        ("currentIpAddress", LP_IP_ADDR_STRING),
        ("ipAddressList", IP_ADDR_STRING),
        ("gatewayList", IP_ADDR_STRING),
        ("dhcpServer", IP_ADDR_STRING),
        ("haveWins", c_uint),
        ("primaryWinsServer", IP_ADDR_STRING),
        ("secondaryWinsServer", IP_ADDR_STRING),
        ("leaseObtained", c_ulong),
        ("leaseExpires", c_ulong)]
    GetAdaptersInfo = windll.iphlpapi.GetAdaptersInfo
    GetAdaptersInfo.restype = c_ulong
    GetAdaptersInfo.argtypes = [LP_IP_ADAPTER_INFO, POINTER(c_ulong)]
    adapterList = (IP_ADAPTER_INFO * 10)()
    buflen = c_ulong(sizeof(adapterList))
    rc = GetAdaptersInfo(byref(adapterList[0]), byref(buflen))
    if rc == 0:
        for a in adapterList:
            adNode = a.ipAddressList
            while True:
                ipAddr = adNode.ipAddress
                if ipAddr:
                    yield ipAddr
                adNode = adNode.next
                if not adNode:
                    break

Usage:

>>> for addr in getIPAddresses():
>>>    print addr
192.168.0.100
10.5.9.207

As it relies on windll, this will work only on Windows.


回答 11

在Debian(经过测试)上,我怀疑大多数Linux都可以。

import commands

RetMyIP = commands.getoutput("hostname -I")

在MS Windows上(已测试)

import socket

socket.gethostbyname(socket.gethostname())

On Debian (tested) and I suspect most Linux’s..

import commands

RetMyIP = commands.getoutput("hostname -I")

On MS Windows (tested)

import socket

socket.gethostbyname(socket.gethostname())

回答 12

我不认为该版本已经发布。我在Ubuntu 12.04上使用python 2.7进行了测试。

在以下位置找到了此解决方案:http : //code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/

import socket
import fcntl
import struct

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

结果示例:

>>> get_ip_address('eth0')
'38.113.228.130'

A version I do not believe that has been posted yet. I tested with python 2.7 on Ubuntu 12.04.

Found this solution at : http://code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/

import socket
import fcntl
import struct

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

Example Result:

>>> get_ip_address('eth0')
'38.113.228.130'

回答 13

Ninjagecko的答案有所不同。这应该在允许UDP广播并且不需要访问LAN或Internet上的地址的任何LAN上都有效。

import socket
def getNetworkIp():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    s.connect(('<broadcast>', 0))
    return s.getsockname()[0]

print (getNetworkIp())

Variation on ninjagecko’s answer. This should work on any LAN that allows UDP broadcast and doesn’t require access to an address on the LAN or internet.

import socket
def getNetworkIp():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    s.connect(('<broadcast>', 0))
    return s.getsockname()[0]

print (getNetworkIp())

回答 14

恐怕除了连接到另一台计算机并将其发送给您的IP地址之外,没有其他任何独立于平台的良好方法。例如: findmyipaddress。请注意,除非您需要的IP地址位于NAT后面,否则这将无法工作,除非要连接的计算机也位于NAT后面。

这是在Linux中工作的一种解决方案: 获取与网络接口关联的IP地址

I’m afraid there aren’t any good platform independent ways to do this other than connecting to another computer and having it send you your IP address. For example: findmyipaddress. Note that this won’t work if you need an IP address that’s behind NAT unless the computer you’re connecting to is behind NAT as well.

Here’s one solution that works in Linux: get the IP address associated with a network interface.


回答 15

通过命令行实用程序产生“干净”输出的一种简单方法:

import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
                         "awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips

它将显示系统上的所有IPv4地址。

One simple way to produce “clean” output via command line utils:

import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
                         "awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips

It will show all IPv4 addresses on the system.


回答 16

仅供参考,我可以验证该方法:

import socket
addr = socket.gethostbyname(socket.gethostname())

在OS X(10.6,10.5),Windows XP和管理良好的RHEL部门服务器上均可使用。它不能在非常小的CentOS VM上工作,而我只是对其进行一些内核黑客攻击。因此,对于该实例,您只需检查127.0.0.1地址,然后执行以下操作:

if addr == "127.0.0.1":
     import commands
     output = commands.getoutput("/sbin/ifconfig")
     addr = parseaddress(output)

然后从输出中解析IP地址。应当注意,默认情况下ifconfig不在普通用户的PATH中,这就是为什么我在命令中提供完整路径的原因。我希望这有帮助。

FYI I can verify that the method:

import socket
addr = socket.gethostbyname(socket.gethostname())

Works in OS X (10.6,10.5), Windows XP, and on a well administered RHEL department server. It did not work on a very minimal CentOS VM that I just do some kernel hacking on. So for that instance you can just check for a 127.0.0.1 address and in that case do the following:

if addr == "127.0.0.1":
     import commands
     output = commands.getoutput("/sbin/ifconfig")
     addr = parseaddress(output)

And then parse the ip address from the output. It should be noted that ifconfig is not in a normal user’s PATH by default and that is why I give the full path in the command. I hope this helps.


回答 17

这是UnkwnTech回答的一种变体,它提供了一个get_local_addr()函数,该函数返回主机的主要LAN ip地址。我发布它是因为这增加了许多东西:ipv6支持,错误处理,忽略localhost / linklocal地址,并使用TESTNET地址(rfc5737)连接。

# imports
import errno
import socket
import logging

# localhost prefixes
_local_networks = ("127.", "0:0:0:0:0:0:0:1")

# ignore these prefixes -- localhost, unspecified, and link-local
_ignored_networks = _local_networks + ("0.", "0:0:0:0:0:0:0:0", "169.254.", "fe80:")

def detect_family(addr):
    if "." in addr:
        assert ":" not in addr
        return socket.AF_INET
    elif ":" in addr:
        return socket.AF_INET6
    else:
        raise ValueError("invalid ipv4/6 address: %r" % addr)

def expand_addr(addr):
    """convert address into canonical expanded form --
    no leading zeroes in groups, and for ipv6: lowercase hex, no collapsed groups.
    """
    family = detect_family(addr)
    addr = socket.inet_ntop(family, socket.inet_pton(family, addr))
    if "::" in addr:
        count = 8-addr.count(":")
        addr = addr.replace("::", (":0" * count) + ":")
        if addr.startswith(":"):
            addr = "0" + addr
    return addr

def _get_local_addr(family, remote):
    try:
        s = socket.socket(family, socket.SOCK_DGRAM)
        try:
            s.connect((remote, 9))
            return s.getsockname()[0]
        finally:
            s.close()
    except socket.error:
        # log.info("trapped error connecting to %r via %r", remote, family, exc_info=True)
        return None

def get_local_addr(remote=None, ipv6=True):
    """get LAN address of host

    :param remote:
        return  LAN address that host would use to access that specific remote address.
        by default, returns address it would use to access the public internet.

    :param ipv6:
        by default, attempts to find an ipv6 address first.
        if set to False, only checks ipv4.

    :returns:
        primary LAN address for host, or ``None`` if couldn't be determined.
    """
    if remote:
        family = detect_family(remote)
        local = _get_local_addr(family, remote)
        if not local:
            return None
        if family == socket.AF_INET6:
            # expand zero groups so the startswith() test works.
            local = expand_addr(local)
        if local.startswith(_local_networks):
            # border case where remote addr belongs to host
            return local
    else:
        # NOTE: the two addresses used here are TESTNET addresses,
        #       which should never exist in the real world.
        if ipv6:
            local = _get_local_addr(socket.AF_INET6, "2001:db8::1234")
            # expand zero groups so the startswith() test works.
            if local:
                local = expand_addr(local)
        else:
            local = None
        if not local:
            local = _get_local_addr(socket.AF_INET, "192.0.2.123")
            if not local:
                return None
    if local.startswith(_ignored_networks):
        return None
    return local

This is a variant of UnkwnTech’s answer — it provides a get_local_addr() function, which returns the primary LAN ip address of the host. I’m posting it because this adds a number of things: ipv6 support, error handling, ignoring localhost/linklocal addrs, and uses a TESTNET addr (rfc5737) to connect to.

# imports
import errno
import socket
import logging

# localhost prefixes
_local_networks = ("127.", "0:0:0:0:0:0:0:1")

# ignore these prefixes -- localhost, unspecified, and link-local
_ignored_networks = _local_networks + ("0.", "0:0:0:0:0:0:0:0", "169.254.", "fe80:")

def detect_family(addr):
    if "." in addr:
        assert ":" not in addr
        return socket.AF_INET
    elif ":" in addr:
        return socket.AF_INET6
    else:
        raise ValueError("invalid ipv4/6 address: %r" % addr)

def expand_addr(addr):
    """convert address into canonical expanded form --
    no leading zeroes in groups, and for ipv6: lowercase hex, no collapsed groups.
    """
    family = detect_family(addr)
    addr = socket.inet_ntop(family, socket.inet_pton(family, addr))
    if "::" in addr:
        count = 8-addr.count(":")
        addr = addr.replace("::", (":0" * count) + ":")
        if addr.startswith(":"):
            addr = "0" + addr
    return addr

def _get_local_addr(family, remote):
    try:
        s = socket.socket(family, socket.SOCK_DGRAM)
        try:
            s.connect((remote, 9))
            return s.getsockname()[0]
        finally:
            s.close()
    except socket.error:
        # log.info("trapped error connecting to %r via %r", remote, family, exc_info=True)
        return None

def get_local_addr(remote=None, ipv6=True):
    """get LAN address of host

    :param remote:
        return  LAN address that host would use to access that specific remote address.
        by default, returns address it would use to access the public internet.

    :param ipv6:
        by default, attempts to find an ipv6 address first.
        if set to False, only checks ipv4.

    :returns:
        primary LAN address for host, or ``None`` if couldn't be determined.
    """
    if remote:
        family = detect_family(remote)
        local = _get_local_addr(family, remote)
        if not local:
            return None
        if family == socket.AF_INET6:
            # expand zero groups so the startswith() test works.
            local = expand_addr(local)
        if local.startswith(_local_networks):
            # border case where remote addr belongs to host
            return local
    else:
        # NOTE: the two addresses used here are TESTNET addresses,
        #       which should never exist in the real world.
        if ipv6:
            local = _get_local_addr(socket.AF_INET6, "2001:db8::1234")
            # expand zero groups so the startswith() test works.
            if local:
                local = expand_addr(local)
        else:
            local = None
        if not local:
            local = _get_local_addr(socket.AF_INET, "192.0.2.123")
            if not local:
                return None
    if local.startswith(_ignored_networks):
        return None
    return local

回答 18

import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]

回答 19

这将适用于大多数linux系统:

import socket, subprocess, re
def get_ipv4_address():
    """
    Returns IP address(es) of current machine.
    :return:
    """
    p = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE)
    ifc_resp = p.communicate()
    patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
    resp = patt.findall(ifc_resp[0])
    print resp

get_ipv4_address()

This will work on most linux boxes:

import socket, subprocess, re
def get_ipv4_address():
    """
    Returns IP address(es) of current machine.
    :return:
    """
    p = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE)
    ifc_resp = p.communicate()
    patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
    resp = patt.findall(ifc_resp[0])
    print resp

get_ipv4_address()

回答 20

这个答案是我个人为解决获得LAN IP问题而进行的个人尝试,因为它socket.gethostbyname(socket.gethostname())也返回了127.0.0.1。此方法不需要Internet,仅需要LAN连接即可。代码适用于Python 3.x,但可以轻松转换为2.x。使用UDP广播:

import select
import socket
import threading
from queue import Queue, Empty

def get_local_ip():
        def udp_listening_server():
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.bind(('<broadcast>', 8888))
            s.setblocking(0)
            while True:
                result = select.select([s],[],[])
                msg, address = result[0][0].recvfrom(1024)
                msg = str(msg, 'UTF-8')
                if msg == 'What is my LAN IP address?':
                    break
            queue.put(address)

        queue = Queue()
        thread = threading.Thread(target=udp_listening_server)
        thread.queue = queue
        thread.start()
        s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        waiting = True
        while waiting:
            s2.sendto(bytes('What is my LAN IP address?', 'UTF-8'), ('<broadcast>', 8888))
            try:
                address = queue.get(False)
            except Empty:
                pass
            else:
                waiting = False
        return address[0]

if __name__ == '__main__':
    print(get_local_ip())

This answer is my personal attempt to solve the problem of getting the LAN IP, since socket.gethostbyname(socket.gethostname()) also returned 127.0.0.1. This method does not require Internet just a LAN connection. Code is for Python 3.x but could easily be converted for 2.x. Using UDP Broadcast:

import select
import socket
import threading
from queue import Queue, Empty

def get_local_ip():
        def udp_listening_server():
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.bind(('<broadcast>', 8888))
            s.setblocking(0)
            while True:
                result = select.select([s],[],[])
                msg, address = result[0][0].recvfrom(1024)
                msg = str(msg, 'UTF-8')
                if msg == 'What is my LAN IP address?':
                    break
            queue.put(address)

        queue = Queue()
        thread = threading.Thread(target=udp_listening_server)
        thread.queue = queue
        thread.start()
        s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        waiting = True
        while waiting:
            s2.sendto(bytes('What is my LAN IP address?', 'UTF-8'), ('<broadcast>', 8888))
            try:
                address = queue.get(False)
            except Empty:
                pass
            else:
                waiting = False
        return address[0]

if __name__ == '__main__':
    print(get_local_ip())

回答 21

127.0.1.1 您的真实IP地址。一般来说,计算机可以具有任意数量的IP地址。您可以为专用网络过滤它们-127.0.0.0/8、10.0.0.0/8、172.16.0.0/12和192.168.0.0/16。

但是,没有跨平台的方法来获取所有IP地址。在Linux上,您可以使用SIOCGIFCONFioctl。

127.0.1.1 is your real IP address. More generally speaking, a computer can have any number of IP addresses. You can filter them for private networks – 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.

However, there is no cross-platform way to get all IP addresses. On Linux, you can use the SIOCGIFCONF ioctl.


回答 22

使用IP命令并返回IPv4和IPv6地址的命令版本略有改进:

import commands,re,socket

#A generator that returns stripped lines of output from "ip address show"
iplines=(line.strip() for line in commands.getoutput("ip address show").split('\n'))

#Turn that into a list of IPv4 and IPv6 address/mask strings
addresses1=reduce(lambda a,v:a+v,(re.findall(r"inet ([\d.]+/\d+)",line)+re.findall(r"inet6 ([\:\da-f]+/\d+)",line) for line in iplines))
#addresses1 now looks like ['127.0.0.1/8', '::1/128', '10.160.114.60/23', 'fe80::1031:3fff:fe00:6dce/64']

#Get a list of IPv4 addresses as (IPstring,subnetsize) tuples
ipv4s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if '.' in addr)]
#ipv4s now looks like [('127.0.0.1', 8), ('10.160.114.60', 23)]

#Get IPv6 addresses
ipv6s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if ':' in addr)]

A slight refinement of the commands version that uses the IP command, and returns IPv4 and IPv6 addresses:

import commands,re,socket

#A generator that returns stripped lines of output from "ip address show"
iplines=(line.strip() for line in commands.getoutput("ip address show").split('\n'))

#Turn that into a list of IPv4 and IPv6 address/mask strings
addresses1=reduce(lambda a,v:a+v,(re.findall(r"inet ([\d.]+/\d+)",line)+re.findall(r"inet6 ([\:\da-f]+/\d+)",line) for line in iplines))
#addresses1 now looks like ['127.0.0.1/8', '::1/128', '10.160.114.60/23', 'fe80::1031:3fff:fe00:6dce/64']

#Get a list of IPv4 addresses as (IPstring,subnetsize) tuples
ipv4s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if '.' in addr)]
#ipv4s now looks like [('127.0.0.1', 8), ('10.160.114.60', 23)]

#Get IPv6 addresses
ipv6s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if ':' in addr)]

回答 23

好了,您可以在GNU / Linux上使用命令“ ip route”来知道您当前的IP地址。

这显示了路由器/调制解调器上运行的DHCP服务器为接口提供的IP。通常,“ 192.168.1.1/24”是本地网络的IP,其中“ 24”表示DHCP服务器在掩码范围内指定的可能IP地址范围。

这是一个示例:请注意,PyNotify只是为了使我的观点更清楚而已,根本不需要

#! /usr/bin/env python

import sys , pynotify

if sys.version_info[1] != 7:
   raise RuntimeError('Python 2.7 And Above Only')       

from subprocess import check_output # Available on Python 2.7+ | N/A 

IP = check_output(['ip', 'route'])
Split_Result = IP.split()

# print Split_Result[2] # Remove "#" to enable

pynotify.init("image")
notify = pynotify.Notification("Ip", "Server Running At:" + Split_Result[2] , "/home/User/wireless.png")    
notify.show()    

这样做的好处是您无需指定网络接口。这在运行套接字服务器时非常有用

您可以使用easy_install甚至Pip安装PyNotify:

easy_install py-notify

要么

pip install py-notify

或在python脚本/解释器中

from pip import main

main(['install', 'py-notify'])

Well you can use the command “ip route” on GNU/Linux to know your current IP address.

This shows the IP given to the interface by the DHCP server running on the router/modem. Usually “192.168.1.1/24” is the IP for local network where “24” means the range of posible IP addresses given by the DHCP server within the mask range.

Here’s an example: Note that PyNotify is just an addition to get my point straight and is not required at all

#! /usr/bin/env python

import sys , pynotify

if sys.version_info[1] != 7:
   raise RuntimeError('Python 2.7 And Above Only')       

from subprocess import check_output # Available on Python 2.7+ | N/A 

IP = check_output(['ip', 'route'])
Split_Result = IP.split()

# print Split_Result[2] # Remove "#" to enable

pynotify.init("image")
notify = pynotify.Notification("Ip", "Server Running At:" + Split_Result[2] , "/home/User/wireless.png")    
notify.show()    

The advantage of this is that you don’t need to specify the network interface. That’s pretty useful when running a socket server

You can install PyNotify using easy_install or even Pip:

easy_install py-notify

or

pip install py-notify

or within python script/interpreter

from pip import main

main(['install', 'py-notify'])

回答 24

如果您正在寻找与本地IP地址不同的IPV4地址127.0.0.1,这是一个整洁的python代码:

import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8') 
address=address[:-1]

也可以单行编写:

address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]

即使您输入localhost/etc/hostname,代码仍会提供您的本地IP地址。

If you’re looking for an IPV4 address different from your localhost IP address 127.0.0.1, here is a neat piece of python codes:

import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8') 
address=address[:-1]

Which can also be written in a single line:

address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]

Even if you put localhost in /etc/hostname, the code will still give your local IP address.


回答 25

对于Linux,可以只使用check_output了的hostname -I,像这样的系统命令:

from subprocess import check_output
check_output(['hostname', '-I'])

For linux, you can just use check_output of the hostname -I system command like so:

from subprocess import check_output
check_output(['hostname', '-I'])

回答 26

注意:这不是使用标准库,而是非常简单。

$ pip安装pif

from pif import get_public_ip
get_public_ip()

Note: This is not using the standard library, but quite simple.

$ pip install pif

from pif import get_public_ip
get_public_ip()

回答 27

netifaces可通过pip和easy_install获得。(我知道,它不在基础中,但是值得安装。)

netifaces的跨平台确实有些奇怪:

  • 不一定总是包含localhost / loop-back接口(Cygwin)。
  • 每个协议列出了地址(例如IPv4,IPv6),每个接口列出了协议。在某些系统(Linux)上,每个协议接口对都有自己的关联接口(使用interface_name:n表示法),而在其他系统(Windows)上,单个接口将具有每个协议的地址列表。在这两种情况下,都有一个协议列表,但是它可能只包含一个元素。

以下是一些netifaces代码可用于:

import netifaces

PROTO = netifaces.AF_INET   # We want only IPv4, for now at least

# Get list of network interfaces
# Note: Can't filter for 'lo' here because Windows lacks it.
ifaces = netifaces.interfaces()

# Get all addresses (of all kinds) for each interface
if_addrs = [netifaces.ifaddresses(iface) for iface in ifaces]

# Filter for the desired address type
if_inet_addrs = [addr[PROTO] for addr in if_addrs if PROTO in addr]

iface_addrs = [s['addr'] for a in if_inet_addrs for s in a if 'addr' in s]
# Can filter for '127.0.0.1' here.

上面的代码不会将地址映射回其接口名称(用于动态生成ebtables / iptables规则)。因此,这是一个将上述信息和接口名称保存在元组中的版本:

import netifaces

PROTO = netifaces.AF_INET   # We want only IPv4, for now at least

# Get list of network interfaces
ifaces = netifaces.interfaces()

# Get addresses for each interface
if_addrs = [(netifaces.ifaddresses(iface), iface) for iface in ifaces]

# Filter for only IPv4 addresses
if_inet_addrs = [(tup[0][PROTO], tup[1]) for tup in if_addrs if PROTO in tup[0]]

iface_addrs = [(s['addr'], tup[1]) for tup in if_inet_addrs for s in tup[0] if 'addr' in s]

而且,不,我不喜欢列表理解。这些天就是我的大脑运作的方式。

以下代码片段将全部打印出来:

from __future__ import print_function  # For 2.x folks
from pprint import pprint as pp

print('\nifaces = ', end='')
pp(ifaces)

print('\nif_addrs = ', end='')
pp(if_addrs)

print('\nif_inet_addrs = ', end='')
pp(if_inet_addrs)

print('\niface_addrs = ', end='')
pp(iface_addrs)

请享用!

netifaces is available via pip and easy_install. (I know, it’s not in base, but it could be worth the install.)

netifaces does have some oddities across platforms:

  • The localhost/loop-back interface may not always be included (Cygwin).
  • Addresses are listed per-protocol (e.g., IPv4, IPv6) and protocols are listed per-interface. On some systems (Linux) each protocol-interface pair has its own associated interface (using the interface_name:n notation) while on other systems (Windows) a single interface will have a list of addresses for each protocol. In both cases there is a protocol list, but it may contain only a single element.

Here’s some netifaces code to play with:

import netifaces

PROTO = netifaces.AF_INET   # We want only IPv4, for now at least

# Get list of network interfaces
# Note: Can't filter for 'lo' here because Windows lacks it.
ifaces = netifaces.interfaces()

# Get all addresses (of all kinds) for each interface
if_addrs = [netifaces.ifaddresses(iface) for iface in ifaces]

# Filter for the desired address type
if_inet_addrs = [addr[PROTO] for addr in if_addrs if PROTO in addr]

iface_addrs = [s['addr'] for a in if_inet_addrs for s in a if 'addr' in s]
# Can filter for '127.0.0.1' here.

The above code doesn’t map an address back to its interface name (useful for generating ebtables/iptables rules on the fly). So here’s a version that keeps the above information with the interface name in a tuple:

import netifaces

PROTO = netifaces.AF_INET   # We want only IPv4, for now at least

# Get list of network interfaces
ifaces = netifaces.interfaces()

# Get addresses for each interface
if_addrs = [(netifaces.ifaddresses(iface), iface) for iface in ifaces]

# Filter for only IPv4 addresses
if_inet_addrs = [(tup[0][PROTO], tup[1]) for tup in if_addrs if PROTO in tup[0]]

iface_addrs = [(s['addr'], tup[1]) for tup in if_inet_addrs for s in tup[0] if 'addr' in s]

And, no, I’m not in love with list comprehensions. It’s just the way my brain works these days.

The following snippet will print it all out:

from __future__ import print_function  # For 2.x folks
from pprint import pprint as pp

print('\nifaces = ', end='')
pp(ifaces)

print('\nif_addrs = ', end='')
pp(if_addrs)

print('\nif_inet_addrs = ', end='')
pp(if_inet_addrs)

print('\niface_addrs = ', end='')
pp(iface_addrs)

Enjoy!


回答 28

使用新引入的asyncio软件包的Python 3.4版本。

async get_local_ip():
    loop = asyncio.get_event_loop()
    transport, protocol = await loop.create_datagram_endpoint(
        asyncio.DatagramProtocol,
        remote_addr=('8.8.8.8', 80))
    result = transport.get_extra_info('sockname')[0])
    transport.close()
    return result

这是基于UnkwnTech的出色回答

A Python 3.4 version utilizing the newly introduced asyncio package.

async get_local_ip():
    loop = asyncio.get_event_loop()
    transport, protocol = await loop.create_datagram_endpoint(
        asyncio.DatagramProtocol,
        remote_addr=('8.8.8.8', 80))
    result = transport.get_extra_info('sockname')[0])
    transport.close()
    return result

This is based on UnkwnTech’s excellent answer.


回答 29

要获取IP地址,您可以直接在python中使用shell命令

import socket, subprocess

def getIpAndHostname():
    hostname =  socket.gethostname()

    shell_cmd = "ifconfig | awk '/inet addr/{print substr($2,6)}'"
    proc = subprocess.Popen([shell_cmd], stdout=subprocess.PIPE, shell=True)
    (out, err) = proc.communicate()

    ip_list = out.split('\n')
    ip = ip_list[0]

    for _ip in ip_list:
        try:
            if _ip != "127.0.0.1" and _ip.split(".")[3] != "1":
                ip = _ip
        except:
            pass
    return ip, hostname

ip_addr, hostname = getIpAndHostname()

To get the ip address you can use a shell command directly in python:

import socket, subprocess

def getIpAndHostname():
    hostname =  socket.gethostname()

    shell_cmd = "ifconfig | awk '/inet addr/{print substr($2,6)}'"
    proc = subprocess.Popen([shell_cmd], stdout=subprocess.PIPE, shell=True)
    (out, err) = proc.communicate()

    ip_list = out.split('\n')
    ip = ip_list[0]

    for _ip in ip_list:
        try:
            if _ip != "127.0.0.1" and _ip.split(".")[3] != "1":
                ip = _ip
        except:
            pass
    return ip, hostname

ip_addr, hostname = getIpAndHostname()

将NumPy数组转储到csv文件中

问题:将NumPy数组转储到csv文件中

有没有办法将NumPy数组转储到CSV文件中?我有一个2D NumPy数组,需要以人类可读的格式转储它。

Is there a way to dump a NumPy array into a CSV file? I have a 2D NumPy array and need to dump it in human-readable format.


回答 0

numpy.savetxt 将数组保存到文本文件。

import numpy
a = numpy.asarray([ [1,2,3], [4,5,6], [7,8,9] ])
numpy.savetxt("foo.csv", a, delimiter=",")

numpy.savetxt saves an array to a text file.

import numpy
a = numpy.asarray([ [1,2,3], [4,5,6], [7,8,9] ])
numpy.savetxt("foo.csv", a, delimiter=",")

回答 1

您可以使用pandas。它确实需要一些额外的内存,因此并不总是可能的,但是它非常快速且易于使用。

import pandas as pd 
pd.DataFrame(np_array).to_csv("path/to/file.csv")

如果您不想要标题或索引,请使用 to_csv("/path/to/file.csv", header=None, index=None)

You can use pandas. It does take some extra memory so it’s not always possible, but it’s very fast and easy to use.

import pandas as pd 
pd.DataFrame(np_array).to_csv("path/to/file.csv")

if you don’t want a header or index, use to_csv("/path/to/file.csv", header=None, index=None)


回答 2

tofile 是执行此操作的便捷功能:

import numpy as np
a = np.asarray([ [1,2,3], [4,5,6], [7,8,9] ])
a.tofile('foo.csv',sep=',',format='%10.5f')

手册页有一些有用的注释:

这是用于快速存储阵列数据的便利功能。有关字节序和精度的信息会丢失,因此对于打算在不同字节序的计算机之间存档数据或传输数据的文件,此方法不是一个好的选择。这些问题中的一些可以通过将数据输出为文本文件来克服,而这是以速度和文件大小为代价的。

注意。此功能不会生成多行的CSV文件,而是将所有内容保存到一行。

tofile is a convenient function to do this:

import numpy as np
a = np.asarray([ [1,2,3], [4,5,6], [7,8,9] ])
a.tofile('foo.csv',sep=',',format='%10.5f')

The man page has some useful notes:

This is a convenience function for quick storage of array data. Information on endianness and precision is lost, so this method is not a good choice for files intended to archive data or transport data between machines with different endianness. Some of these problems can be overcome by outputting the data as text files, at the expense of speed and file size.

Note. This function does not produce multi-line csv files, it saves everything to one line.


回答 3

将记录数组编写为带有标题的CSV文件需要更多的工作。

本示例读取标题为第一行的CSV文件,然后写入相同的文件。

import numpy as np

# Write an example CSV file with headers on first line
with open('example.csv', 'w') as fp:
    fp.write('''\
col1,col2,col3
1,100.1,string1
2,222.2,second string
''')

# Read it as a Numpy record array
ar = np.recfromcsv('example.csv')
print(repr(ar))
# rec.array([(1, 100.1, 'string1'), (2, 222.2, 'second string')], 
#           dtype=[('col1', '<i4'), ('col2', '<f8'), ('col3', 'S13')])

# Write as a CSV file with headers on first line
with open('out.csv', 'w') as fp:
    fp.write(','.join(ar.dtype.names) + '\n')
    np.savetxt(fp, ar, '%s', ',')

请注意,此示例不考虑带逗号的字符串。要考虑非数字数据的引号,请使用以下csv软件包:

import csv

with open('out2.csv', 'wb') as fp:
    writer = csv.writer(fp, quoting=csv.QUOTE_NONNUMERIC)
    writer.writerow(ar.dtype.names)
    writer.writerows(ar.tolist())

Writing record arrays as CSV files with headers requires a bit more work.

This example reads a CSV file with the header on the first line, then writes the same file.

import numpy as np

# Write an example CSV file with headers on first line
with open('example.csv', 'w') as fp:
    fp.write('''\
col1,col2,col3
1,100.1,string1
2,222.2,second string
''')

# Read it as a Numpy record array
ar = np.recfromcsv('example.csv')
print(repr(ar))
# rec.array([(1, 100.1, 'string1'), (2, 222.2, 'second string')], 
#           dtype=[('col1', '<i4'), ('col2', '<f8'), ('col3', 'S13')])

# Write as a CSV file with headers on first line
with open('out.csv', 'w') as fp:
    fp.write(','.join(ar.dtype.names) + '\n')
    np.savetxt(fp, ar, '%s', ',')

Note that this example does not consider strings with commas. To consider quotes for non-numeric data, use the csv package:

import csv

with open('out2.csv', 'wb') as fp:
    writer = csv.writer(fp, quoting=csv.QUOTE_NONNUMERIC)
    writer.writerow(ar.dtype.names)
    writer.writerows(ar.tolist())

回答 4

如前所述,将数组转储为CSV文件的最佳方法是使用.savetxt(...)方法。但是,有些事情我们应该知道如何正确完成。

例如,如果您有一个带dtype = np.int32as 的numpy数组

   narr = np.array([[1,2],
                 [3,4],
                 [5,6]], dtype=np.int32)

并想另存savetxt

np.savetxt('values.csv', narr, delimiter=",")

它将数据以浮点指数格式存储为

1.000000000000000000e+00,2.000000000000000000e+00
3.000000000000000000e+00,4.000000000000000000e+00
5.000000000000000000e+00,6.000000000000000000e+00

你必须使用一个名为参数更改格式fmt

np.savetxt('values.csv', narr, fmt="%d", delimiter=",")

以原始格式存储数据

以压缩的gz格式保存数据

此外,savetxt还可用于以.gz压缩格式存储数据,这在通过网络传输数据时可能很有用。

我们只需要更改文件的扩展名,因为.gznumpy会自动处理所有内容

np.savetxt('values.gz', narr, fmt="%d", delimiter=",")

希望能帮助到你

As already discussed, the best way to dump the array into a CSV file is by using .savetxt(...)method. However, there are certain things we should know to do it properly.

For example, if you have a numpy array with dtype = np.int32 as

   narr = np.array([[1,2],
                 [3,4],
                 [5,6]], dtype=np.int32)

and want to save using savetxt as

np.savetxt('values.csv', narr, delimiter=",")

It will store the data in floating point exponential format as

1.000000000000000000e+00,2.000000000000000000e+00
3.000000000000000000e+00,4.000000000000000000e+00
5.000000000000000000e+00,6.000000000000000000e+00

You will have to change the formatting by using a parameter called fmt as

np.savetxt('values.csv', narr, fmt="%d", delimiter=",")

to store data in its original format

Saving Data in Compressed gz format

Also, savetxt can be used for storing data in .gz compressed format which might be useful while transferring data over network.

We just need to change the extension of the file as .gz and numpy will take care of everything automatically

np.savetxt('values.gz', narr, fmt="%d", delimiter=",")

Hope it helps


回答 5

我相信您也可以很简单地完成此操作,如下所示:

  1. 将Numpy数组转换为Pandas数据框
  2. 另存为CSV

例如#1:

    # Libraries to import
    import pandas as pd
    import nump as np

    #N x N numpy array (dimensions dont matter)
    corr_mat    #your numpy array
    my_df = pd.DataFrame(corr_mat)  #converting it to a pandas dataframe

例如#2:

    #save as csv 
    my_df.to_csv('foo.csv', index=False)   # "foo" is the name you want to give
                                           # to csv file. Make sure to add ".csv"
                                           # after whatever name like in the code

I believe you can also accomplish this quite simply as follows:

  1. Convert Numpy array into a Pandas dataframe
  2. Save as CSV

e.g. #1:

    # Libraries to import
    import pandas as pd
    import nump as np

    #N x N numpy array (dimensions dont matter)
    corr_mat    #your numpy array
    my_df = pd.DataFrame(corr_mat)  #converting it to a pandas dataframe

e.g. #2:

    #save as csv 
    my_df.to_csv('foo.csv', index=False)   # "foo" is the name you want to give
                                           # to csv file. Make sure to add ".csv"
                                           # after whatever name like in the code

回答 6

如果要在列中写:

    for x in np.nditer(a.T, order='C'): 
            file.write(str(x))
            file.write("\n")

这里的“ a”是numpy数组的名称,“文件”是要写入文件的变量。

如果要写在行中:

    writer= csv.writer(file, delimiter=',')
    for x in np.nditer(a.T, order='C'): 
            row.append(str(x))
    writer.writerow(row)

if you want to write in column:

    for x in np.nditer(a.T, order='C'): 
            file.write(str(x))
            file.write("\n")

Here ‘a’ is the name of numpy array and ‘file’ is the variable to write in a file.

If you want to write in row:

    writer= csv.writer(file, delimiter=',')
    for x in np.nditer(a.T, order='C'): 
            row.append(str(x))
    writer.writerow(row)

回答 7

如果要将numpy数组(例如your_array = np.array([[1,2],[3,4]]))保存到一个单元格,可以先使用进行转换your_array.tolist()

然后将其以正常方式保存到一个单元格中,并且delimiter=';' 和,csv文件中的单元格将如下所示[[1, 2], [2, 4]]

然后,您可以像这样恢复阵列: your_array = np.array(ast.literal_eval(cell_string))

If you want to save your numpy array (e.g. your_array = np.array([[1,2],[3,4]])) to one cell, you could convert it first with your_array.tolist().

Then save it the normal way to one cell, with delimiter=';' and the cell in the csv-file will look like this [[1, 2], [2, 4]]

Then you could restore your array like this: your_array = np.array(ast.literal_eval(cell_string))


回答 8

您也可以使用纯python而不使用任何模块来完成此操作。

# format as a block of csv text to do whatever you want
csv_rows = ["{},{}".format(i, j) for i, j in array]
csv_text = "\n".join(csv_rows)

# write it to a file
with open('file.csv', 'w') as f:
    f.write(csv_text)

You can also do it with pure python without using any modules.

# format as a block of csv text to do whatever you want
csv_rows = ["{},{}".format(i, j) for i, j in array]
csv_text = "\n".join(csv_rows)

# write it to a file
with open('file.csv', 'w') as f:
    f.write(csv_text)

回答 9

在Python中,我们使用csv.writer()模块将数据写入csv文件。该模块类似于csv.reader()模块。

import csv

person = [['SN', 'Person', 'DOB'],
['1', 'John', '18/1/1997'],
['2', 'Marie','19/2/1998'],
['3', 'Simon','20/3/1999'],
['4', 'Erik', '21/4/2000'],
['5', 'Ana', '22/5/2001']]

csv.register_dialect('myDialect',
delimiter = '|',
quoting=csv.QUOTE_NONE,
skipinitialspace=True)

with open('dob.csv', 'w') as f:
    writer = csv.writer(f, dialect='myDialect')
    for row in person:
       writer.writerow(row)

f.close()

定界符是用于分隔字段的字符串。默认值为comma(,)。

In Python we use csv.writer() module to write data into csv files. This module is similar to the csv.reader() module.

import csv

person = [['SN', 'Person', 'DOB'],
['1', 'John', '18/1/1997'],
['2', 'Marie','19/2/1998'],
['3', 'Simon','20/3/1999'],
['4', 'Erik', '21/4/2000'],
['5', 'Ana', '22/5/2001']]

csv.register_dialect('myDialect',
delimiter = '|',
quoting=csv.QUOTE_NONE,
skipinitialspace=True)

with open('dob.csv', 'w') as f:
    writer = csv.writer(f, dialect='myDialect')
    for row in person:
       writer.writerow(row)

f.close()

A delimiter is a string used to separate fields. The default value is comma(,).


从Python中的字符串中删除特定字符

问题:从Python中的字符串中删除特定字符

我正在尝试使用Python从字符串中删除特定字符。这是我现在正在使用的代码。不幸的是,它似乎对字符串没有任何作用。

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

如何正确执行此操作?

I’m trying to remove specific characters from a string using Python. This is the code I’m using right now. Unfortunately it appears to do nothing to the string.

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

How do I do this properly?


回答 0

Python中的字符串是不可变的(无法更改)。因此,的效果line.replace(...)只是创建一个新字符串,而不是更改旧字符串。您需要重新绑定(分配)它line,以使该变量采用新值,并删除这些字符。

而且,相对而言,您的操作方式会比较缓慢。这也可能会使经验丰富的pythonator感到有些困惑,他们将看到双重嵌套的结构,并暂时认为会发生一些更复杂的事情。

从Python 2.6和更高版本的Python 2.x版本*开始,您可以改用str.translate,(但请继续阅读Python 3的不同之处):

line = line.translate(None, '!@#$')

或将正则表达式替换为 re.sub

import re
line = re.sub('[!@#$]', '', line)

方括号内的字符构成一个字符类line该类中的所有字符都被替换为第二个参数sub:空字符串。

在Python 3中,字符串是Unicode。您必须进行一些不同的翻译。kevpie在对其中一个答案的评论中提到了这一点,并在的文档中str.translate对此进行了注明。

当调用translateUnicode字符串的方法时,您不能传递上面使用的第二个参数。您也不能None作为第一个参数传递。相反,您将翻译表(通常是字典)作为唯一参数传递。此表将字符的序号值(即调用ord它们的结果)映射到应替换它们的字符的序号值,或者(对我们有用)None表示应删除它们。

因此,使用Unicode字符串进行上述舞蹈时,您会调用类似

translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)

在此处dict.fromkeysmap用于简要生成包含以下内容的字典

{ord('!'): None, ord('@'): None, ...}

就像另一个答案所说的那样,甚至更简单,在原位创建翻译表:

unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

或使用创建相同的翻译表str.maketrans

unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))

*为了与早期的Python兼容,您可以创建一个“空”转换表来代替None

import string
line = line.translate(string.maketrans('', ''), '!@#$')

string.maketrans是用来创建转换表的,它只是一个字符串,其中包含序号为0到255的字符。

Strings in Python are immutable (can’t be changed). Because of this, the effect of line.replace(...) is just to create a new string, rather than changing the old one. You need to rebind (assign) it to line in order to have that variable take the new value, with those characters removed.

Also, the way you are doing it is going to be kind of slow, relatively. It’s also likely to be a bit confusing to experienced pythonators, who will see a doubly-nested structure and think for a moment that something more complicated is going on.

Starting in Python 2.6 and newer Python 2.x versions *, you can instead use str.translate, (but read on for Python 3 differences):

line = line.translate(None, '!@#$')

or regular expression replacement with re.sub

import re
line = re.sub('[!@#$]', '', line)

The characters enclosed in brackets constitute a character class. Any characters in line which are in that class are replaced with the second parameter to sub: an empty string.

In Python 3, strings are Unicode. You’ll have to translate a little differently. kevpie mentions this in a comment on one of the answers, and it’s noted in the documentation for str.translate.

When calling the translate method of a Unicode string, you cannot pass the second parameter that we used above. You also can’t pass None as the first parameter. Instead, you pass a translation table (usually a dictionary) as the only parameter. This table maps the ordinal values of characters (i.e. the result of calling ord on them) to the ordinal values of the characters which should replace them, or—usefully to us—None to indicate that they should be deleted.

So to do the above dance with a Unicode string you would call something like

translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)

Here dict.fromkeys and map are used to succinctly generate a dictionary containing

{ord('!'): None, ord('@'): None, ...}

Even simpler, as another answer puts it, create the translation table in place:

unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

Or create the same translation table with str.maketrans:

unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))

* for compatibility with earlier Pythons, you can create a “null” translation table to pass in place of None:

import string
line = line.translate(string.maketrans('', ''), '!@#$')

Here string.maketrans is used to create a translation table, which is just a string containing the characters with ordinal values 0 to 255.


回答 1

我是否在这里遗漏了要点,或者只是以下内容:

string = "ab1cd1ef"
string = string.replace("1","") 

print string
# result: "abcdef"

将其循环:

a = "a!b@c#d$"
b = "!@#$"
for char in b:
    a = a.replace(char,"")

print a
# result: "abcd"

Am I missing the point here, or is it just the following:

string = "ab1cd1ef"
string = string.replace("1","") 

print string
# result: "abcdef"

Put it in a loop:

a = "a!b@c#d$"
b = "!@#$"
for char in b:
    a = a.replace(char,"")

print a
# result: "abcd"

回答 2

>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if  c not in '?:!/;' )
'abc#@efg12'
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if  c not in '?:!/;' )
'abc#@efg12'

回答 3

re.sub从Python 3.5开始具有正则表达式

re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

>>> import re

>>> line = 'Q: Do I write ;/.??? No!!!'

>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'

说明

正则表达式(regex)中,|它是逻辑OR,并\转义可能是实际regex命令的空格和特殊字符。而sub代表替换,在这种情况下为空字符串''

Easy peasy with re.sub regular expression as of Python 3.5

re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

Example

>>> import re

>>> line = 'Q: Do I write ;/.??? No!!!'

>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'

Explanation

In regular expressions (regex), | is a logical OR and \ escapes spaces and special characters that might be actual regex commands. Whereas sub stands for substitution, in this case with the empty string ''.


回答 4

对于允许在字符串中使用某些字符的相反要求,可以将正则表达式与集合补码运算符配合使用[^ABCabc]。例如,要删除除ASCII字母,数字和连字符以外的所有内容,请执行以下操作:

>>> import string
>>> import re
>>>
>>> phrase = '  There were "nine" (9) chick-peas in my pocket!!!      '
>>> allow = string.letters + string.digits + '-'
>>> re.sub('[^%s]' % allow, '', phrase)

'Therewerenine9chick-peasinmypocket'

python正则表达式文档中

可以通过补充集合来匹配不在范围内的字符。如果集合的第一个字符是'^',则所有不在集合中的字符都将被匹配。例如,[^5]将匹配除“ 5”以外的任何字符,并将匹配除以外的[^^]任何字符 '^'^如果不是集合中的第一个字符,则没有特殊含义。

For the inverse requirement of only allowing certain characters in a string, you can use regular expressions with a set complement operator [^ABCabc]. For example, to remove everything except ascii letters, digits, and the hyphen:

>>> import string
>>> import re
>>>
>>> phrase = '  There were "nine" (9) chick-peas in my pocket!!!      '
>>> allow = string.letters + string.digits + '-'
>>> re.sub('[^%s]' % allow, '', phrase)

'Therewerenine9chick-peasinmypocket'

From the python regular expression documentation:

Characters that are not within a range can be matched by complementing the set. If the first character of the set is '^', all the characters that are not in the set will be matched. For example, [^5] will match any character except ‘5’, and [^^] will match any character except '^'. ^ has no special meaning if it’s not the first character in the set.


回答 5

询问者几乎拥有了它。像Python中的大多数事物一样,答案比您想象的要简单。

>>> line = "H E?.LL!/;O:: "  
>>> for char in ' ?.!/;:':  
...  line = line.replace(char,'')  
...
>>> print line
HELLO

您不必执行嵌套的if / for循环操作,但是您需要单独检查每个字符。

The asker almost had it. Like most things in Python, the answer is simpler than you think.

>>> line = "H E?.LL!/;O:: "  
>>> for char in ' ?.!/;:':  
...  line = line.replace(char,'')  
...
>>> print line
HELLO

You don’t have to do the nested if/for loop thing, but you DO need to check each character individually.


回答 6

line = line.translate(None, " ?.!/;:")
line = line.translate(None, " ?.!/;:")

回答 7

>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'

回答 8

字符串在Python中是不可变的。replace替换后,该方法返回一个新字符串。尝试:

for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')

Strings are immutable in Python. The replace method returns a new string after the replacement. Try:

for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')

回答 9

令我惊讶的是,还没有人建议使用内置过滤器功能。

    import operator
    import string # only for the example you could use a custom string

    s = "1212edjaq"

假设我们要过滤掉所有不是数字的内容。使用过滤器内置方法“ …等效于生成器表达式(如果函数(item),则为可迭代的项目项)” [ Python 3内置:过滤器 ]

    sList = list(s)
    intsList = list(string.digits)
    obj = filter(lambda x: operator.contains(intsList, x), sList)))

在Python 3中返回

    >>  <filter object @ hex>

要获得打印的字符串,

    nums = "".join(list(obj))
    print(nums)
    >> "1212"

我不确定过滤器在效率方面如何排名,但是知道如何在进行列表理解等时使用过滤器是一件好事。

更新

从逻辑上讲,由于过滤器可以工作,因此您还可以使用列表理解功能,并且据我所读,由于lambda是编程功能领域的华尔街对冲基金经理,因此应该更有效。另一个优点是它是一种单线,不需要任何进口。例如,使用上面定义的相同字符串“ s”,

      num = "".join([i for i in s if i.isdigit()])

而已。返回值将是原始字符串中所有数字字符的字符串。

如果您有可接受/不可接受字符的特定列表,则只需调整列表理解的’if’部分。

      target_chars = "".join([i for i in s if i in some_list]) 

或者,

      target_chars = "".join([i for i in s if i not in some_list])

I was surprised that no one had yet recommended using the builtin filter function.

    import operator
    import string # only for the example you could use a custom string

    s = "1212edjaq"

Say we want to filter out everything that isn’t a number. Using the filter builtin method “…is equivalent to the generator expression (item for item in iterable if function(item))” [Python 3 Builtins: Filter]

    sList = list(s)
    intsList = list(string.digits)
    obj = filter(lambda x: operator.contains(intsList, x), sList)))

In Python 3 this returns

    >>  <filter object @ hex>

To get a printed string,

    nums = "".join(list(obj))
    print(nums)
    >> "1212"

I am not sure how filter ranks in terms of efficiency but it is a good thing to know how to use when doing list comprehensions and such.

UPDATE

Logically, since filter works you could also use list comprehension and from what I have read it is supposed to be more efficient because lambdas are the wall street hedge fund managers of the programming function world. Another plus is that it is a one-liner that doesnt require any imports. For example, using the same string ‘s’ defined above,

      num = "".join([i for i in s if i.isdigit()])

That’s it. The return will be a string of all the characters that are digits in the original string.

If you have a specific list of acceptable/unacceptable characters you need only adjust the ‘if’ part of the list comprehension.

      target_chars = "".join([i for i in s if i in some_list]) 

or alternatively,

      target_chars = "".join([i for i in s if i not in some_list])

回答 10

使用filter,您只需要一行

line = filter(lambda char: char not in " ?.!/;:", line)

这会将字符串视为可迭代的,并检查每个字符是否lambda返回True

>>> help(filter)
Help on built-in function filter in module __builtin__:

filter(...)
    filter(function or None, sequence) -> list, tuple, or string

    Return those items of sequence for which function(item) is true.  If
    function is None, return the items that are true.  If sequence is a tuple
    or string, return the same type, else return a list.

Using filter, you’d just need one line

line = filter(lambda char: char not in " ?.!/;:", line)

This treats the string as an iterable and checks every character if the lambda returns True:

>>> help(filter)
Help on built-in function filter in module __builtin__:

filter(...)
    filter(function or None, sequence) -> list, tuple, or string

    Return those items of sequence for which function(item) is true.  If
    function is None, return the items that are true.  If sequence is a tuple
    or string, return the same type, else return a list.

回答 11

这是完成此任务的一些可能方法:

def attempt1(string):
    return "".join([v for v in string if v not in ("a", "e", "i", "o", "u")])


def attempt2(string):
    for v in ("a", "e", "i", "o", "u"):
        string = string.replace(v, "")
    return string


def attempt3(string):
    import re
    for v in ("a", "e", "i", "o", "u"):
        string = re.sub(v, "", string)
    return string


def attempt4(string):
    return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "")


for attempt in [attempt1, attempt2, attempt3, attempt4]:
    print(attempt("murcielago"))

PS:示例中使用的是元音…,而不是“?。!/ ;:”,是的,“ murcielago”是西班牙语中用来说蝙蝠的单词…有趣的词,因为它包含所有元音

PS2:如果您对性能感兴趣,可以使用以下简单代码来衡量这些尝试:

import timeit


K = 1000000
for i in range(1,5):
    t = timeit.Timer(
        f"attempt{i}('murcielago')",
        setup=f"from __main__ import attempt{i}"
    ).repeat(1, K)
    print(f"attempt{i}",min(t))

在我的盒子里,你会得到:

attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465

因此,对于这种特定输入,似乎try4是最快的尝试。

Here’s some possible ways to achieve this task:

def attempt1(string):
    return "".join([v for v in string if v not in ("a", "e", "i", "o", "u")])


def attempt2(string):
    for v in ("a", "e", "i", "o", "u"):
        string = string.replace(v, "")
    return string


def attempt3(string):
    import re
    for v in ("a", "e", "i", "o", "u"):
        string = re.sub(v, "", string)
    return string


def attempt4(string):
    return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "")


for attempt in [attempt1, attempt2, attempt3, attempt4]:
    print(attempt("murcielago"))

PS: Instead using ” ?.!/;:” the examples use the vowels… and yeah, “murcielago” is the Spanish word to say bat… funny word as it contains all the vowels :)

PS2: If you’re interested on performance you could measure these attempts with a simple code like:

import timeit


K = 1000000
for i in range(1,5):
    t = timeit.Timer(
        f"attempt{i}('murcielago')",
        setup=f"from __main__ import attempt{i}"
    ).repeat(1, K)
    print(f"attempt{i}",min(t))

In my box you’d get:

attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465

So it seems attempt4 is the fastest one for this particular input.


回答 12

这是我的Python 2/3兼容版本。由于翻译API已更改。

def remove(str_, chars):
    """Removes each char in `chars` from `str_`.

    Args:
        str_: String to remove characters from
        chars: String of to-be removed characters

    Returns:
        A copy of str_ with `chars` removed

    Example:
            remove("What?!?: darn;", " ?.!:;") => 'Whatdarn'
    """
    try:
        # Python2.x
        return str_.translate(None, chars)
    except TypeError:
        # Python 3.x
        table = {ord(char): None for char in chars}
        return str_.translate(table)

Here’s my Python 2/3 compatible version. Since the translate api has changed.

def remove(str_, chars):
    """Removes each char in `chars` from `str_`.

    Args:
        str_: String to remove characters from
        chars: String of to-be removed characters

    Returns:
        A copy of str_ with `chars` removed

    Example:
            remove("What?!?: darn;", " ?.!:;") => 'Whatdarn'
    """
    try:
        # Python2.x
        return str_.translate(None, chars)
    except TypeError:
        # Python 3.x
        table = {ord(char): None for char in chars}
        return str_.translate(table)

回答 13

#!/usr/bin/python
import re

strs = "how^ much for{} the maple syrup? $20.99? That's[] ricidulous!!!"
print strs
nstr = re.sub(r'[?|$|.|!|a|b]',r' ',strs)#i have taken special character to remove but any #character can be added here
print nstr
nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)#for removing special character
print nestr
#!/usr/bin/python
import re

strs = "how^ much for{} the maple syrup? $20.99? That's[] ricidulous!!!"
print strs
nstr = re.sub(r'[?|$|.|!|a|b]',r' ',strs)#i have taken special character to remove but any #character can be added here
print nstr
nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)#for removing special character
print nestr

回答 14

这个怎么样:

def text_cleanup(text):
    new = ""
    for i in text:
        if i not in " ?.!/;:":
            new += i
    return new

How about this:

def text_cleanup(text):
    new = ""
    for i in text:
        if i not in " ?.!/;:":
            new += i
    return new

回答 15

您还可以使用一个函数,以使用列表替换其他种类的正则表达式或其他模式。这样,您就可以混合使用正则表达式,字符类和真正的基本文本模式。当您需要替换许多HTML元素时,它非常有用。

*注意:适用于Python 3.x

import re  # Regular expression library


def string_cleanup(x, notwanted):
    for item in notwanted:
        x = re.sub(item, '', x)
    return x

line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)

# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)

# Get rid of special characters
special_chars = ["[!@#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)

在函数string_cleanup中,它将字符串x和不需要的列表作为参数。对于该元素或模式列表中的每个项目,如果需要替代,它将完成。

输出:

Uncleaned:  <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean:  My example: A text %very% $clean!!
2nd clean:  My example: A text very clean

You can also use a function in order to substitute different kind of regular expression or other pattern with the use of a list. With that, you can mixed regular expression, character class, and really basic text pattern. It’s really useful when you need to substitute a lot of elements like HTML ones.

*NB: works with Python 3.x

import re  # Regular expression library


def string_cleanup(x, notwanted):
    for item in notwanted:
        x = re.sub(item, '', x)
    return x

line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)

# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)

# Get rid of special characters
special_chars = ["[!@#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)

In the function string_cleanup, it takes your string x and your list notwanted as arguments. For each item in that list of elements or pattern, if a substitute is needed it will be done.

The output:

Uncleaned:  <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean:  My example: A text %very% $clean!!
2nd clean:  My example: A text very clean

回答 16

我使用的方法可能无法有效地工作,但是它非常简单。我可以使用切片和格式化功能一次删除不同位置的多个字符。这是一个例子:

words = "things"
removed = "%s%s" % (words[:3], words[-1:])

这将导致“删除”中带有“ this”一词。

格式化对于在打印字符串中途打印变量非常有用。它可以使用插入任何数据类型,后跟变量的数据类型。所有数据类型都可以使用%s,而浮点数(也就是小数)和整数可以使用%d

切片可用于对字符串的复杂控制。当我输入words [:3]时,它允许我从字符串的开头选择所有字符(冒号在数字之前,这意味着“从开头到”)到第四个字符(包括第四个字符)字符)。之所以3等于第4位是因为Python从0开始。然后,当我将word [-1:]放到最后时,倒数第二个字符(冒号在数字后面)。放置-1将使Python从最后符开始计数,而不是从第一个字符开始计数。同样,Python将从0开始。因此,单词[-1:]基本上表示’从倒数第二个字符到字符串的末尾。

因此,通过剪掉我要删除的字符之前的字符,之后要剪掉的字符并将它们夹在中间,我可以删除不需要的字符。想起来像香肠。中间很脏,所以我想摆脱它。我只剪掉我想要的两端,然后将它们放在一起,中间没有多余的部分。

如果要删除多个连续的字符,只需在[](切片部分)中移动数字即可。或者,如果我想从不同位置删除多个字符,则可以一次将多个切片夹在一起。

例子:

 words = "control"
 removed = "%s%s" % (words[:2], words[-2:])

已移除等于“酷”。

words = "impacts"
removed = "%s%s%s" % (words[1], words[3:5], words[-1])

已移除等于“ macs”。

在这种情况下,[3:5]表示位置 3到位置处的字符位置的 5的字符(不包括最终位置的字符)。

请记住,Python从0开始计数,因此您也需要这样做。

My method I’d use probably wouldn’t work as efficiently, but it is massively simple. I can remove multiple characters at different positions all at once, using slicing and formatting. Here’s an example:

words = "things"
removed = "%s%s" % (words[:3], words[-1:])

This will result in ‘removed’ holding the word ‘this’.

Formatting can be very helpful for printing variables midway through a print string. It can insert any data type using a % followed by the variable’s data type; all data types can use %s, and floats (aka decimals) and integers can use %d.

Slicing can be used for intricate control over strings. When I put words[:3], it allows me to select all the characters in the string from the beginning (the colon is before the number, this will mean ‘from the beginning to’) to the 4th character (it includes the 4th character). The reason 3 equals till the 4th position is because Python starts at 0. Then, when I put word[-1:], it means the 2nd last character to the end (the colon is behind the number). Putting -1 will make Python count from the last character, rather than the first. Again, Python will start at 0. So, word[-1:] basically means ‘from the second last character to the end of the string.

So, by cutting off the characters before the character I want to remove and the characters after and sandwiching them together, I can remove the unwanted character. Think of it like a sausage. In the middle it’s dirty, so I want to get rid of it. I simply cut off the two ends I want then put them together without the unwanted part in the middle.

If I want to remove multiple consecutive characters, I simply shift the numbers around in the [] (slicing part). Or if I want to remove multiple characters from different positions, I can simply sandwich together multiple slices at once.

Examples:

 words = "control"
 removed = "%s%s" % (words[:2], words[-2:])

removed equals ‘cool’.

words = "impacts"
removed = "%s%s%s" % (words[1], words[3:5], words[-1])

removed equals ‘macs’.

In this case, [3:5] means character at position 3 through character at position 5 (excluding the character at the final position).

Remember, Python starts counting at 0, so you will need to as well.


回答 17

试试这个:

def rm_char(original_str, need2rm):
    ''' Remove charecters in "need2rm" from "original_str" '''
    return original_str.translate(str.maketrans('','',need2rm))

此方法在python 3.5.2中很好用

Try this one:

def rm_char(original_str, need2rm):
    ''' Remove charecters in "need2rm" from "original_str" '''
    return original_str.translate(str.maketrans('','',need2rm))

This method works well in python 3.5.2


回答 18

您可以使用re模块的正则表达式替换。使用^表达式可让您从字符串中准确选择所需的内容。

    import re
    text = "This is absurd!"
    text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
    print(text)

输出为“ Thisisabsurd”。仅出现在^符号后指定的内容。

You could use the re module’s regular expression replacement. Using the ^ expression allows you to pick exactly what you want from your string.

    import re
    text = "This is absurd!"
    text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
    print(text)

Output to this would be “Thisisabsurd”. Only things specified after the ^ symbol will appear.


回答 19

字符串方法replace不会修改原始字符串。它保留原始文件,并返回修改后的副本。

您想要的是这样的: line = line.replace(char,'')

def replace_all(line, )for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')
    return line

但是,每次删除一个字符时都创建一个新字符串是非常低效的。我建议改为以下内容:

def replace_all(line, baddies, *):
    """
    The following is documentation on how to use the class,
    without reference to the implementation details:

    For implementation notes, please see comments begining with `#`
    in the source file.

    [*crickets chirp*]

    """

    is_bad = lambda ch, baddies=baddies: return ch in baddies
    filter_baddies = lambda ch, *, is_bad=is_bad: "" if is_bad(ch) else ch
    mahp = replace_all.map(filter_baddies, line)
    return replace_all.join('', join(mahp))

    # -------------------------------------------------
    # WHY `baddies=baddies`?!?
    #     `is_bad=is_bad`
    # -------------------------------------------------
    # Default arguments to a lambda function are evaluated
    # at the same time as when a lambda function is
    # **defined**.
    #
    # global variables of a lambda function
    # are evaluated when the lambda function is
    # **called**
    #
    # The following prints "as yellow as snow"
    #
    #     fleece_color = "white"
    #     little_lamb = lambda end: return "as " + fleece_color + end
    #
    #     # sometime later...
    #
    #     fleece_color = "yellow"
    #     print(little_lamb(" as snow"))
    # --------------------------------------------------
replace_all.map = map
replace_all.join = str.join

The string method replace does not modify the original string. It leaves the original alone and returns a modified copy.

What you want is something like: line = line.replace(char,'')

def replace_all(line, )for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')
    return line

However, creating a new string each and every time that a character is removed is very inefficient. I recommend the following instead:

def replace_all(line, baddies, *):
    """
    The following is documentation on how to use the class,
    without reference to the implementation details:

    For implementation notes, please see comments begining with `#`
    in the source file.

    [*crickets chirp*]

    """

    is_bad = lambda ch, baddies=baddies: return ch in baddies
    filter_baddies = lambda ch, *, is_bad=is_bad: "" if is_bad(ch) else ch
    mahp = replace_all.map(filter_baddies, line)
    return replace_all.join('', join(mahp))

    # -------------------------------------------------
    # WHY `baddies=baddies`?!?
    #     `is_bad=is_bad`
    # -------------------------------------------------
    # Default arguments to a lambda function are evaluated
    # at the same time as when a lambda function is
    # **defined**.
    #
    # global variables of a lambda function
    # are evaluated when the lambda function is
    # **called**
    #
    # The following prints "as yellow as snow"
    #
    #     fleece_color = "white"
    #     little_lamb = lambda end: return "as " + fleece_color + end
    #
    #     # sometime later...
    #
    #     fleece_color = "yellow"
    #     print(little_lamb(" as snow"))
    # --------------------------------------------------
replace_all.map = map
replace_all.join = str.join

回答 20

下面的一个..不使用正则表达式的概念..

ipstring ="text with symbols!@#$^&*( ends here"
opstring=''
for i in ipstring:
    if i.isalnum()==1 or i==' ':
        opstring+=i
    pass
print opstring

Below one.. with out using regular expression concept..

ipstring ="text with symbols!@#$^&*( ends here"
opstring=''
for i in ipstring:
    if i.isalnum()==1 or i==' ':
        opstring+=i
    pass
print opstring

回答 21

在Python 3.5中

例如,

os.rename(file_name, file_name.translate({ord(c): None for c in '0123456789'}))

从字符串中删除所有数字

In Python 3.5

e.g.,

os.rename(file_name, file_name.translate({ord(c): None for c in '0123456789'}))

To remove all the number from the string


回答 22

你可以使用设置

    charlist = list(set(string.digits+string.ascii_uppercase) - set('10IO'))
    return ''.join([random.SystemRandom().choice(charlist) for _ in range(passlen)])

you can use set

    charlist = list(set(string.digits+string.ascii_uppercase) - set('10IO'))
    return ''.join([random.SystemRandom().choice(charlist) for _ in range(passlen)])

回答 23

递归拆分: s = string; chars =要删除的字符

def strip(s,chars):
if len(s)==1:
    return "" if s in chars else s
return strip(s[0:int(len(s)/2)],chars) +  strip(s[int(len(s)/2):len(s)],chars)

例:

print(strip("Hello!","lo"))    #He!

Recursive split: s=string ; chars=chars to remove

def strip(s,chars):
if len(s)==1:
    return "" if s in chars else s
return strip(s[0:int(len(s)/2)],chars) +  strip(s[int(len(s)/2):len(s)],chars)

example:

print(strip("Hello!","lo"))    #He!

回答 24

#为目录中的每个文件重命名文件名

   file_list = os.listdir (r"D:\Dev\Python")

   for file_name in file_list:

       os.rename(file_name, re.sub(r'\d+','',file_name))

# for each file on a directory, rename filename

   file_list = os.listdir (r"D:\Dev\Python")

   for file_name in file_list:

       os.rename(file_name, re.sub(r'\d+','',file_name))

回答 25

即使是以下方法也可以

line = "a,b,c,d,e"
alpha = list(line)
        while ',' in alpha:
            alpha.remove(',')
finalString = ''.join(alpha)
print(finalString)

输出: abcde

Even the below approach works

line = "a,b,c,d,e"
alpha = list(line)
        while ',' in alpha:
            alpha.remove(',')
finalString = ''.join(alpha)
print(finalString)

output: abcde


回答 26

>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'
>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'

在python中创建具有特定大小的空列表

问题:在python中创建具有特定大小的空列表

我想创建一个可以容纳10个元素的空列表(或最好的方法)。

之后,我想在该列表中分配值,例如,应该显示0到9:

s1 = list();
for i in range(0,9):
   s1[i] = i

print  s1

但是当我运行此代码时,它会生成错误,或者在其他情况下,它只会显示 [](空)。

有人可以解释为什么吗?

I want to create an empty list (or whatever is the best way) that can hold 10 elements.

After that I want to assign values in that list, for example this is supposed to display 0 to 9:

s1 = list();
for i in range(0,9):
   s1[i] = i

print  s1

But when I run this code, it generates an error or in another case it just displays [] (empty).

Can someone explain why?


回答 0

您不能分配给类似的列表lst[i] = something,除非该列表已至少已使用i+1元素初始化。您需要使用append将元素添加到列表的末尾。lst.append(something)

(如果使用字典,则可以使用分配符号)。

创建一个空列表:

>>> l = [None] * 10
>>> l
[None, None, None, None, None, None, None, None, None, None]

为上述列表的现有元素分配一个值:

>>> l[1] = 5
>>> l
[None, 5, None, None, None, None, None, None, None, None]

请记住,类似 l[15] = 5仍然会失败,因为我们的列表只有10个元素。

range(x)从[0,1,2,… x-1]创建一个列表

# 2.X only. Use list(range(10)) in 3.X.
>>> l = range(10)
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

使用函数创建列表:

>>> def display():
...     s1 = []
...     for i in range(9): # This is just to tell you how to create a list.
...         s1.append(i)
...     return s1
... 
>>> print display()
[0, 1, 2, 3, 4, 5, 6, 7, 8]

列表理解(使用正方形,因为对于范围您不需要执行所有这些操作,您只需返回即可range(0,9)):

>>> def display():
...     return [x**2 for x in range(9)]
... 
>>> print display()
[0, 1, 4, 9, 16, 25, 36, 49, 64]

You cannot assign to a list like lst[i] = something, unless the list already is initialized with at least i+1 elements. You need to use append to add elements to the end of the list. lst.append(something).

(You could use the assignment notation if you were using a dictionary).

Creating an empty list:

>>> l = [None] * 10
>>> l
[None, None, None, None, None, None, None, None, None, None]

Assigning a value to an existing element of the above list:

>>> l[1] = 5
>>> l
[None, 5, None, None, None, None, None, None, None, None]

Keep in mind that something like l[15] = 5 would still fail, as our list has only 10 elements.

range(x) creates a list from [0, 1, 2, … x-1]

# 2.X only. Use list(range(10)) in 3.X.
>>> l = range(10)
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Using a function to create a list:

>>> def display():
...     s1 = []
...     for i in range(9): # This is just to tell you how to create a list.
...         s1.append(i)
...     return s1
... 
>>> print display()
[0, 1, 2, 3, 4, 5, 6, 7, 8]

List comprehension (Using the squares because for range you don’t need to do all this, you can just return range(0,9) ):

>>> def display():
...     return [x**2 for x in range(9)]
... 
>>> print display()
[0, 1, 4, 9, 16, 25, 36, 49, 64]

回答 1

尝试以下方法:

lst = [None] * 10

上面将创建一个大小为10的列表,其中每个位置都初始化为None。之后,您可以向其中添加元素:

lst = [None] * 10
for i in range(10):
    lst[i] = i

诚然,这不是Python的做事方式。最好这样做:

lst = []
for i in range(10):
    lst.append(i)

更简单的一点是,在Python 2.x中,您可以执行以下操作以初始化值从0到9的列表:

lst = range(10)

在Python 3.x中:

lst = list(range(10))

Try this instead:

lst = [None] * 10

The above will create a list of size 10, where each position is initialized to None. After that, you can add elements to it:

lst = [None] * 10
for i in range(10):
    lst[i] = i

Admittedly, that’s not the Pythonic way to do things. Better do this:

lst = []
for i in range(10):
    lst.append(i)

Or even simpler, in Python 2.x you can do this to initialize a list with values from 0 to 9:

lst = range(10)

And in Python 3.x:

lst = list(range(10))

回答 2

varunl当前接受的答案

 >>> l = [None] * 10
 >>> l
 [None, None, None, None, None, None, None, None, None, None]

对于数字等非引用类型,效果很好。不幸的是,如果您要创建列表列表,则会遇到引用错误。Python 2.7.6中的示例:

>>> a = [[]]*10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(0)
>>> a
[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
>>> 

如您所见,每个元素都指向相同的列表对象。为了解决这个问题,您可以创建一个将每个位置初始化为不同对象引用的方法。

def init_list_of_objects(size):
    list_of_objects = list()
    for i in range(0,size):
        list_of_objects.append( list() ) #different object reference each time
    return list_of_objects


>>> a = init_list_of_objects(10)
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(0)
>>> a
[[0], [], [], [], [], [], [], [], [], []]
>>> 

可能有一种默认的内置python方式(而不是编写函数)来执行此操作,但是我不确定它是什么。很高兴得到纠正!

编辑:这是 [ [] for _ in range(10)]

范例:

>>> [ [random.random() for _ in range(2) ] for _ in range(5)]
>>> [[0.7528051908943816, 0.4325669600055032], [0.510983236521753, 0.7789949902294716], [0.09475179523690558, 0.30216475640534635], [0.3996890132468158, 0.6374322093017013], [0.3374204010027543, 0.4514925173253973]]

varunl’s currently accepted answer

 >>> l = [None] * 10
 >>> l
 [None, None, None, None, None, None, None, None, None, None]

Works well for non-reference types like numbers. Unfortunately if you want to create a list-of-lists you will run into referencing errors. Example in Python 2.7.6:

>>> a = [[]]*10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(0)
>>> a
[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
>>> 

As you can see, each element is pointing to the same list object. To get around this, you can create a method that will initialize each position to a different object reference.

def init_list_of_objects(size):
    list_of_objects = list()
    for i in range(0,size):
        list_of_objects.append( list() ) #different object reference each time
    return list_of_objects


>>> a = init_list_of_objects(10)
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a[0].append(0)
>>> a
[[0], [], [], [], [], [], [], [], [], []]
>>> 

There is likely a default, built-in python way of doing this (instead of writing a function), but I’m not sure what it is. Would be happy to be corrected!

Edit: It’s [ [] for _ in range(10)]

Example :

>>> [ [random.random() for _ in range(2) ] for _ in range(5)]
>>> [[0.7528051908943816, 0.4325669600055032], [0.510983236521753, 0.7789949902294716], [0.09475179523690558, 0.30216475640534635], [0.3996890132468158, 0.6374322093017013], [0.3374204010027543, 0.4514925173253973]]

回答 3

您可以.append(element)进入列表,例如:s1.append(i)。您当前要执行的操作是访问s1[i]不存在的元素()。

You can .append(element) to the list, e.g.: s1.append(i). What you are currently trying to do is access an element (s1[i]) that does not exist.


回答 4

有两种“快速”方法:

x = length_of_your_list
a = [None]*x
# or
a = [None for _ in xrange(x)]

似乎[None]*x更快:

>>> from timeit import timeit
>>> timeit("[None]*100",number=10000)
0.023542165756225586
>>> timeit("[None for _ in xrange(100)]",number=10000)
0.07616496086120605

但是,如果您可以接受范围(例如[0,1,2,3,...,x-1]),则range(x)可能最快:

>>> timeit("range(100)",number=10000)
0.012513160705566406

There are two “quick” methods:

x = length_of_your_list
a = [None]*x
# or
a = [None for _ in xrange(x)]

It appears that [None]*x is faster:

>>> from timeit import timeit
>>> timeit("[None]*100",number=10000)
0.023542165756225586
>>> timeit("[None for _ in xrange(100)]",number=10000)
0.07616496086120605

But if you are ok with a range (e.g. [0,1,2,3,...,x-1]), then range(x) might be fastest:

>>> timeit("range(100)",number=10000)
0.012513160705566406

回答 5

我很惊讶没有人建议使用这种简单的方法来创建一个空列表。这是一个旧线程,但仅出于完整性目的添加它。这将创建一个包含10个空列表的列表

x = [[] for i in range(10)]

I’m surprised nobody suggest this simple approach to creating a list of empty lists. This is an old thread, but just adding this for completeness. This will create a list of 10 empty lists

x = [[] for i in range(10)]

回答 6

(这是根据问题的原始版本编写的。)

我想创建一个空列表(或最好的方法)以容纳10个元素。

所有列表可以容纳任意数量的元素,仅受可用内存的限制。列表中唯一重要的“大小”是当前列表中的元素数量。

但是当我运行它时,结果是[]

print display s1语法无效;根据您对所看到内容的描述,我认为您的意思是display(s1)然后print s1。为此,您必须预先定义一个全局s1变量以传递给该函数。

呼叫display并不会像书面那样修改您传入的列表。您的代码说:“ s1是传递给函数的任何事物的名称;好的,现在我们要做的第一件事是完全忘记该事物,让我们s1开始引用一个新创建的事物list。现在我们将对其进行修改。list ”。这对您传递的值没有影响。

没有理由在此处传递值。(创建一个函数也没有真正的理由,但这并不重要。)您想“创建”某些东西,这就是函数的输出。创建您所描述的事物不需要任何信息,因此请勿传递任何信息。要获取信息,return它。

那会给你类似的东西:

def display():
    s1 = list();
    for i in range(0, 9):
        s1[i] = i
    return s1

您将要注意的下一个问题是列表实际上仅包含9个元素,因为该range函数跳过了终点。(作为旁注,其[]效果与一样好list(),并且不需要分号,它s1是变量的较差名称,并且range如果从0。开始,则只需要一个参数。)因此,最后得到

def create_list():
    result = list()
    for i in range(10):
        result[i] = i
    return result

但是,这仍然没有实现。range是不是这就是语言的一部分的方式一些神奇的关键字fordef是,而是它的一个功能。猜猜该函数返回什么?没错-这些整数的列表。所以整个功能都崩溃了

def create_list():
    return range(10)

现在您了解了为什么我们根本不需要自己编写函数;range已经是我们要寻找的功能。同样,尽管没有必要或没有理由“调整”列表大小。

(This was written based on the original version of the question.)

I want to create a empty list (or whatever is the best way) can hold 10 elements.

All lists can hold as many elements as you like, subject only to the limit of available memory. The only “size” of a list that matters is the number of elements currently in it.

but when I run it, the result is []

print display s1 is not valid syntax; based on your description of what you’re seeing, I assume you meant display(s1) and then print s1. For that to run, you must have previously defined a global s1 to pass into the function.

Calling display does not modify the list you pass in, as written. Your code says “s1 is a name for whatever thing was passed in to the function; ok, now the first thing we’ll do is forget about that thing completely, and let s1 start referring instead to a newly created list. Now we’ll modify that list“. This has no effect on the value you passed in.

There is no reason to pass in a value here. (There is no real reason to create a function, either, but that’s beside the point.) You want to “create” something, so that is the output of your function. No information is required to create the thing you describe, so don’t pass any information in. To get information out, return it.

That would give you something like:

def display():
    s1 = list();
    for i in range(0, 9):
        s1[i] = i
    return s1

The next problem you will note is that your list will actually have only 9 elements, because the end point is skipped by the range function. (As side notes, [] works just as well as list(), the semicolon is unnecessary, s1 is a poor name for the variable, and only one parameter is needed for range if you’re starting from 0.) So then you end up with

def create_list():
    result = list()
    for i in range(10):
        result[i] = i
    return result

However, this is still missing the mark; range is not some magical keyword that’s part of the language the way for and def are, but instead it’s a function. And guess what that function returns? That’s right – a list of those integers. So the entire function collapses to

def create_list():
    return range(10)

and now you see why we don’t need to write a function ourselves at all; range is already the function we’re looking for. Although, again, there is no need or reason to “pre-size” the list.


回答 7

我感到惊讶的是,创建这些初始化列表的最简单方法不在这些答案中。只需在list函数中使用生成器:

list(range(9))

I’m a bit surprised that the easiest way to create an initialised list is not in any of these answers. Just use a generator in the list function:

list(range(9))

回答 8

n使用嵌套列表推导创建尺寸二维矩阵的一种简单方法:

m = [[None for _ in range(n)] for _ in range(n)]

One simple way to create a 2D matrix of size n using nested list comprehensions:

m = [[None for _ in range(n)] for _ in range(n)]

回答 9

这是我在python中的2D列表的代码,它将显示为no。输入的行数:

empty = []
row = int(input())

for i in range(row):
    temp = list(map(int, input().split()))
    empty.append(temp)

for i in empty:
    for j in i:
        print(j, end=' ')
    print('')

Here’s my code for 2D list in python which would read no. of rows from the input :

empty = []
row = int(input())

for i in range(row):
    temp = list(map(int, input().split()))
    empty.append(temp)

for i in empty:
    for j in i:
        print(j, end=' ')
    print('')

回答 10

我在寻找类似问题时遇到了这样的问题。我必须构建一个2D数组,然后用字典中的元素替换每个列表(在2D数组中)的某些元素。然后,我碰上了这个 SO问题,这帮助了我,也许这将帮助其他初学者得到解决。关键技巧是将2D数组初始化为numpy数组,然后使用array[i,j]代替array[i][j]

作为参考,这是我不得不使用的代码:

nd_array = []
for i in range(30):
    nd_array.append(np.zeros(shape = (32,1)))
new_array = []
for i in range(len(lines)):
    new_array.append(nd_array)
new_array = np.asarray(new_array)
for i in range(len(lines)):
    splits = lines[i].split(' ')
    for j in range(len(splits)):
        #print(new_array[i][j])
        new_array[i,j] = final_embeddings[dictionary[str(splits[j])]-1].reshape(32,1)

现在我知道我们可以使用列表理解了,但是为了简单起见,我使用了一个嵌套的for循环。希望这对遇到这篇文章的其他人有所帮助。

I came across this SO question while searching for a similar problem. I had to build a 2D array and then replace some elements of each list (in 2D array) with elements from a dict. I then came across this SO question which helped me, maybe this will help other beginners to get around. The key trick was to initialize the 2D array as an numpy array and then using array[i,j] instead of array[i][j].

For reference this is the piece of code where I had to use this :

nd_array = []
for i in range(30):
    nd_array.append(np.zeros(shape = (32,1)))
new_array = []
for i in range(len(lines)):
    new_array.append(nd_array)
new_array = np.asarray(new_array)
for i in range(len(lines)):
    splits = lines[i].split(' ')
    for j in range(len(splits)):
        #print(new_array[i][j])
        new_array[i,j] = final_embeddings[dictionary[str(splits[j])]-1].reshape(32,1)

Now I know we can use list comprehension but for simplicity sake I am using a nested for loop. Hope this helps others who come across this post.


回答 11

使它作为功能更可重用。

def createEmptyList(length,fill=None):
    '''
    return a (empty) list of a given length
    Example:
        print createEmptyList(3,-1)
        >> [-1, -1, -1]
        print createEmptyList(4)
        >> [None, None, None, None]
    '''
    return [fill] * length

Make it more reusable as a function.

def createEmptyList(length,fill=None):
    '''
    return a (empty) list of a given length
    Example:
        print createEmptyList(3,-1)
        >> [-1, -1, -1]
        print createEmptyList(4)
        >> [None, None, None, None]
    '''
    return [fill] * length

回答 12

s1 = []
for i in range(11):
   s1.append(i)

print s1

要创建列表,只需使用以下方括号:“ []”

要将某些内容添加到列表中,请使用list.append()

s1 = []
for i in range(11):
   s1.append(i)

print s1

To create a list, just use these brackets: “[]”

To add something to a list, use list.append()


回答 13

此代码生成一个包含10个随机数的数组。

import random
numrand=[]
for i in range(0,10):
   a = random.randint(1,50)
   numrand.append(a)
   print(a,i)
print(numrand)

This code generates an array that contains 10 random numbers.

import random
numrand=[]
for i in range(0,10):
   a = random.randint(1,50)
   numrand.append(a)
   print(a,i)
print(numrand)

在Python中将列表转换为元组

问题:在Python中将列表转换为元组

我正在尝试将列表转换为元组。

Google上的大多数解决方案都提供以下代码:

l = [4,5,6]
tuple(l)

但是,运行该代码会导致错误消息:

TypeError:“元组”对象不可调用如何解决此问题?

I’m trying to convert a list to a tuple.

Most solutions on Google offer the following code:

l = [4,5,6]
tuple(l)

However, the code results in an error message when I run it:

TypeError: ‘tuple’ object is not callable How can I fix this problem?


回答 0

它应该工作正常。不要使用tuplelist或其他特殊的名字作为变量名。这可能是导致您出现问题的原因。

>>> l = [4,5,6]
>>> tuple(l)
(4, 5, 6)

It should work fine. Don’t use tuple, list or other special names as a variable name. It’s probably what’s causing your problem.

>>> l = [4,5,6]
>>> tuple(l)
(4, 5, 6)

回答 1

扩展eumiro的注释,通常tuple(l)会将列表l转换为元组:

In [1]: l = [4,5,6]

In [2]: tuple
Out[2]: <type 'tuple'>

In [3]: tuple(l)
Out[3]: (4, 5, 6)

但是,如果您已重新定义tuple为元组而不是type tuple

In [4]: tuple = tuple(l)

In [5]: tuple
Out[5]: (4, 5, 6)

那么您会收到TypeError,因为元组本身不可调用:

In [6]: tuple(l)
TypeError: 'tuple' object is not callable

您可以tuple通过退出并重新启动解释器来恢复原始定义,或者(感谢@glglgl):

In [6]: del tuple

In [7]: tuple
Out[7]: <type 'tuple'>

Expanding on eumiro’s comment, normally tuple(l) will convert a list l into a tuple:

In [1]: l = [4,5,6]

In [2]: tuple
Out[2]: <type 'tuple'>

In [3]: tuple(l)
Out[3]: (4, 5, 6)

However, if you’ve redefined tuple to be a tuple rather than the type tuple:

In [4]: tuple = tuple(l)

In [5]: tuple
Out[5]: (4, 5, 6)

then you get a TypeError since the tuple itself is not callable:

In [6]: tuple(l)
TypeError: 'tuple' object is not callable

You can recover the original definition for tuple by quitting and restarting your interpreter, or (thanks to @glglgl):

In [6]: del tuple

In [7]: tuple
Out[7]: <type 'tuple'>

回答 2

您可能已经做过这样的事情:

>>> tuple = 45, 34  # You used `tuple` as a variable here
>>> tuple
(45, 34)
>>> l = [4, 5, 6]
>>> tuple(l)   # Will try to invoke the variable `tuple` rather than tuple type.

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    tuple(l)
TypeError: 'tuple' object is not callable
>>>
>>> del tuple  # You can delete the object tuple created earlier to make it work
>>> tuple(l)
(4, 5, 6)

这是问题所在…由于您使用了tuple变量来保存tuple (45, 34)较早的内容…所以,现在tupleobject类型tuple

它不再是一个type,因此不再Callable

Never使用任何内置类型作为变量名…您确实可以使用任何其他名称。请为变量使用任意名称…

You might have done something like this:

>>> tuple = 45, 34  # You used `tuple` as a variable here
>>> tuple
(45, 34)
>>> l = [4, 5, 6]
>>> tuple(l)   # Will try to invoke the variable `tuple` rather than tuple type.

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    tuple(l)
TypeError: 'tuple' object is not callable
>>>
>>> del tuple  # You can delete the object tuple created earlier to make it work
>>> tuple(l)
(4, 5, 6)

Here’s the problem… Since you have used a tuple variable to hold a tuple (45, 34) earlier… So, now tuple is an object of type tuple now…

It is no more a type and hence, it is no more Callable.

Never use any built-in types as your variable name… You do have any other name to use. Use any arbitrary name for your variable instead…


回答 3

tuple(l)自Python> =起,要向中添加其他替代方法,3.5您可以执行以下操作:

t = *l,  # or t = (*l,) 

简短一点快,但可能是从可读性受到影响。

这实际上将列表解压缩到l元组文字中,该元组文字是由于单个逗号的存在而创建的,


Ps:您收到的错误是由于名称的掩盖所致,tuple即您在某处(例如)分配了名称元组tuple = (1, 2, 3)

使用del tuple您应该很好。

To add another alternative to tuple(l), as of Python >= 3.5 you can do:

t = *l,  # or t = (*l,) 

short, a bit faster but probably suffers from readability.

This essentially unpacks the list l inside a tuple literal which is created due to the presence of the single comma ,.


P.s: The error you are receiving is due to masking of the name tuple i.e you assigned to the name tuple somewhere e.g tuple = (1, 2, 3).

Using del tuple you should be good to go.


回答 4

我找到了许多最新的答案,并且得到了正确答案,但会为答案添加一些新内容。

在Python有无限的方法可以做到这一点,这里有一些情况下,
正常的方式

>>> l= [1,2,"stackoverflow","python"]
>>> l
[1, 2, 'stackoverflow', 'python']
>>> tup = tuple(l)
>>> type(tup)
<type 'tuple'>
>>> tup
(1, 2, 'stackoverflow', 'python')

聪明的方法

>>>tuple(item for item in l)
(1, 2, 'stackoverflow', 'python')

请记住,元组是不变的,用于存储有价值的东西。例如,密码,密钥或哈希存储在元组或字典中。如果需要刀,为什么要用剑切苹果。明智地使用它,还可以使您的程序高效。

I find many answers up to date and properly answered but will add something new to stack of answers.

In python there are infinite ways to do this, here are some instances
Normal way

>>> l= [1,2,"stackoverflow","python"]
>>> l
[1, 2, 'stackoverflow', 'python']
>>> tup = tuple(l)
>>> type(tup)
<type 'tuple'>
>>> tup
(1, 2, 'stackoverflow', 'python')

smart way

>>>tuple(item for item in l)
(1, 2, 'stackoverflow', 'python')

Remember tuple is immutable ,used for storing something valuable. For example password,key or hashes are stored in tuples or dictionaries. If knife is needed why to use sword to cut apples. Use it wisely, it will also make your program efficient.


TypeError:“模块”对象不可调用

问题:TypeError:“模块”对象不可调用

File "C:\Users\Administrator\Documents\Mibot\oops\blinkserv.py", line 82, in __init__
    self.serv = socket(AF_INET,SOCK_STREAM)
TypeError: 'module' object is not callable

为什么会出现此错误?我糊涂了。

您需要知道什么才能回答我的问题?

File "C:\Users\Administrator\Documents\Mibot\oops\blinkserv.py", line 82, in __init__
    self.serv = socket(AF_INET,SOCK_STREAM)
TypeError: 'module' object is not callable

Why am I getting this error? I’m confused.

What do you need to know to answer my question?


回答 0

socket是一个包含class的模块socket

您需要执行socket.socket(...)以下操作from socket import socket

>>> import socket
>>> socket
<module 'socket' from 'C:\Python27\lib\socket.pyc'>
>>> socket.socket
<class 'socket._socketobject'>
>>>
>>> from socket import socket
>>> socket
<class 'socket._socketobject'>

这就是错误消息的含义:
它表示为module object is not callable,因为您的代码正在调用模块对象。模块对象是导入模块时得到的东西的类型。您试图做的是在模块对象中调用恰好与包含它的模块同名的对象。

这是一种从逻辑上分解这种错误的方法:

  • module object is not callable。Python告诉我我的代码试图调用无法调用的内容。我的代码试图调用什么?”
  • “代码正在尝试调用socket。那应该是可以调用的!变量socket是我认为的吗?”
  • 我应该打印出什么是插座并检查 print socket

socket is a module, containing the class socket.

You need to do socket.socket(...) or from socket import socket:

>>> import socket
>>> socket
<module 'socket' from 'C:\Python27\lib\socket.pyc'>
>>> socket.socket
<class 'socket._socketobject'>
>>>
>>> from socket import socket
>>> socket
<class 'socket._socketobject'>

This is what the error message means:
It says module object is not callable, because your code is calling a module object. A module object is the type of thing you get when you import a module. What you were trying to do is to call a class object within the module object that happens to have the same name as the module that contains it.

Here is a way to logically break down this sort of error:

  • module object is not callable. Python is telling me my code trying to call something that cannot be called. What is my code trying to call?”
  • “The code is trying to call on socket. That should be callable! Is the variable socket is what I think it is?`
  • I should print out what socket is and check print socket

回答 1

假设YourClass.py的内容是:

class YourClass:
    # ......

如果您使用:

from YourClassParentDir import YourClass  # means YourClass.py

这样,我得到TypeError:如果您随后尝试使用‘module’对象,则该对象不可调用YourClass()

但是,如果您使用:

from YourClassParentDir.YourClass import YourClass   # means Class YourClass

或使用YourClass.YourClass(),它对我有用。

Assume that the content of YourClass.py is:

class YourClass:
    # ......

If you use:

from YourClassParentDir import YourClass  # means YourClass.py

In this way, I got TypeError: ‘module’ object is not callable if you then tried to use YourClass().

But, if you use:

from YourClassParentDir.YourClass import YourClass   # means Class YourClass

or use YourClass.YourClass(), it works for me.


回答 2

添加到__init__.pyYourClassParentDir中的主目录,例如:

from .YourClass import YourClass

然后,将类导入另一个脚本时,您将准备好该类的实例:

from YourClassParentDir import YourClass

Add to the main __init__.py in YourClassParentDir, e.g.:

from .YourClass import YourClass

Then, you will have an instance of your class ready when you import it into another script:

from YourClassParentDir import YourClass

回答 3

这是另一个陷阱,即使阅读了这些帖子,我也花了一段时间。我正在设置一个脚本来调用我的python bin脚本。我也无法调用该模块。

我的字形是我正在执行以下操作:

from mypackage.bin import myscript
...
myscript(...)

当我的Zag需要执行以下操作时:

from mypackage.bin.myscript import myscript
...
myscript(...)

总之,请仔细检查您的程序包和模块嵌套。

我正在尝试做的是拥有一个没有* .py扩展名的脚本目录,并且仍然将“ bin”模块放入mypackage / bin中,而这些扩展名具有我的* .py扩展名。我是包装的新手,在解释标准时要遵循这些标准。所以,我在安装根目录下:

setup.py
scripts/
      script1
mypackage/
   bin/
      script1.py
   subpackage1/
   subpackage_etc/

如果这不符合标准,请告诉我。

Here is another gotcha, that took me awhile to see even after reading these posts. I was setting up a script to call my python bin scripts. I was getting the module not callable too.

My zig was that I was doing the following:

from mypackage.bin import myscript
...
myscript(...)

when my zag needed to do the following:

from mypackage.bin.myscript import myscript
...
myscript(...)

In summary, double check your package and module nesting.

What I am trying to do is have a scripts directory that does not have the *.py extension, and still have the ‘bin’ modules to be in mypackage/bin and these have my *.py extension. I am new to packaging, and trying to follow the standards as I am interpreting them. So, I have at the setup root:

setup.py
scripts/
      script1
mypackage/
   bin/
      script1.py
   subpackage1/
   subpackage_etc/

If this is not compliant with standard, please let me know.


回答 4

看来您完成的操作是将socket模块导入为import socket。因此socket是模块。您或者需要将该行更改为self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM),以及将该socket模块的所有其他用法更改为1,或者将import语句更改为from socket import socket

或者你有一个import socket你的后from socket import *

>>> from socket import *
>>> serv = socket(AF_INET,SOCK_STREAM)
>>> import socket
>>> serv = socket(AF_INET,SOCK_STREAM)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'module' object is not callable

It seems like what you’ve done is imported the socket module as import socket. Therefore socket is the module. You either need to change that line to self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM), as well as every other use of the socket module, or change the import statement to from socket import socket.

Or you’ve got an import socket after your from socket import *:

>>> from socket import *
>>> serv = socket(AF_INET,SOCK_STREAM)
>>> import socket
>>> serv = socket(AF_INET,SOCK_STREAM)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'module' object is not callable

回答 5

我知道这个线程已经使用了一年,但是真正的问题出在您的工作目录中。

我相信工作目录是C:\Users\Administrator\Documents\Mibot\oops\。请检查socket.py在此目录中命名的文件。找到它后,对其进行重命名或移动。导入套接字时,socket.py将使用当前目录中的内容,而不是使用socket.pyPython目录中的内容。希望这会有所帮助。:)

注意:切勿使用Python目录中的文件名来保存程序的文件名。它将与您的程序冲突。

I know this thread is a year old, but the real problem is in your working directory.

I believe that the working directory is C:\Users\Administrator\Documents\Mibot\oops\. Please check for the file named socket.py in this directory. Once you find it, rename or move it. When you import socket, socket.py from the current directory is used instead of the socket.py from Python’s directory. Hope this helped. :)

Note: Never use the file names from Python’s directory to save your program’s file name; it will conflict with your program(s).


回答 6

在setup.py中配置console_scripts入口点时,我发现当端点是模块或程序包而不是模块中的函数时,存在此问题。

Traceback (most recent call last):
   File "/Users/ubuntu/.virtualenvs/virtualenv/bin/mycli", line 11, in <module>
load_entry_point('my-package', 'console_scripts', 'mycli')()
TypeError: 'module' object is not callable

例如

from setuptools import setup
setup (
# ...
    entry_points = {
        'console_scripts': [mycli=package.module.submodule]
    },
# ...
)

本来应该

from setuptools import setup
setup (
# ...
    entry_points = {
        'console_scripts': [mycli=package.module.submodule:main]
    },
# ...
)

这样它将引用可调用函数,而不是模块本身。如果模块具有if __name__ == '__main__':块,这似乎没有什么区别。这将不会使该模块可调用。

When configuring an console_scripts entrypoint in setup.py I found this issue existed when the endpoint was a module or package rather than a function within the module.

Traceback (most recent call last):
   File "/Users/ubuntu/.virtualenvs/virtualenv/bin/mycli", line 11, in <module>
load_entry_point('my-package', 'console_scripts', 'mycli')()
TypeError: 'module' object is not callable

For example

from setuptools import setup
setup (
# ...
    entry_points = {
        'console_scripts': [mycli=package.module.submodule]
    },
# ...
)

Should have been

from setuptools import setup
setup (
# ...
    entry_points = {
        'console_scripts': [mycli=package.module.submodule:main]
    },
# ...
)

So that it would refer to a callable function rather than the module itself. It seems to make no difference if the module has a if __name__ == '__main__': block. This will not make the module callable.


回答 7

我想您已经通过设置全局变量“ module”来覆盖了内置函数/变量或其他“ module”。只需打印模块,看看其中有什么。

I guess you have overridden the builtin function/variable or something else “module” by setting the global variable “module”. just print the module see whats in it.


回答 8

由于模块不可调用,请检查导入语句。在Python中,所有东西(包括函数,方法,模块,类等)都是一个对象。

check the import statements since a module is not callable. In Python, everything (including functions, methods, modules, classes etc.) is an object.


回答 9

解决此问题的一种简单方法是导出PYTHONPATH变量环境。例如,对于Debian / GNU Linux中的Python 2.6:

export PYTHONPATH=/usr/lib/python2.6`

在其他操作系统中,您首先要找到该模块或socket.py文件的位置。

A simple way to solve this problem is export thePYTHONPATH variable enviroment. For example, for Python 2.6 in Debian/GNU Linux:

export PYTHONPATH=/usr/lib/python2.6`

In other operating systems, you would first find the location of this module or the socket.py file.


如何导入给定名称的模块为字符串?

问题:如何导入给定名称的模块为字符串?

我正在编写一个以命令作为参数的Python应用程序,例如:

$ python myapp.py command1

我希望应用程序是可扩展的,也就是说,能够添加实现新命令的新模块而不必更改主应用程序源。这棵树看起来像:

myapp/
    __init__.py
    commands/
        __init__.py
        command1.py
        command2.py
    foo.py
    bar.py

因此,我希望该应用程序在运行时找到可用的命令模块并执行适当的命令模块。

Python定义了__import__函数,该函数采用一个字符串作为模块名称:

__import __(name,globals = None,locals = None,fromlist =(),level = 0)

该函数导入模块名称,可能使用给定的全局变量和局部变量来确定如何在程序包上下文中解释该名称。fromlist提供应从名称给定的模块中导入的对象或子模块的名称。

来源:https : //docs.python.org/3/library/functions.html# import

所以目前我有类似的东西:

command = sys.argv[1]
try:
    command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
    # Display error message

command_module.run()

这工作得很好,我只是想知道是否可能有一种更惯用的方式来完成我们对这段代码所做的工作。

请注意,我特别不想使用鸡蛋或延伸点。这不是一个开源项目,我不希望有“插件”。关键是简化主应用程序代码,并且每次添加新命令模块时都无需对其进行修改。

I’m writing a Python application that takes as a command as an argument, for example:

$ python myapp.py command1

I want the application to be extensible, that is, to be able to add new modules that implement new commands without having to change the main application source. The tree looks something like:

myapp/
    __init__.py
    commands/
        __init__.py
        command1.py
        command2.py
    foo.py
    bar.py

So I want the application to find the available command modules at runtime and execute the appropriate one.

Python defines an __import__ function, which takes a string for a module name:

__import__(name, globals=None, locals=None, fromlist=(), level=0)

The function imports the module name, potentially using the given globals and locals to determine how to interpret the name in a package context. The fromlist gives the names of objects or submodules that should be imported from the module given by name.

Source: https://docs.python.org/3/library/functions.html#import

So currently I have something like:

command = sys.argv[1]
try:
    command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
    # Display error message

command_module.run()

This works just fine, I’m just wondering if there is possibly a more idiomatic way to accomplish what we are doing with this code.

Note that I specifically don’t want to get in to using eggs or extension points. This is not an open-source project and I don’t expect there to be “plugins”. The point is to simplify the main application code and remove the need to modify it each time a new command module is added.


回答 0

使用2.7 / 3.1之前的Python,这就是您要做的事情。

对于较新的版本,看到importlib.import_modulePython的2和和Python 3中

您也可以使用exec

或者,__import__您可以通过执行以下操作导入模块列表:

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

直接从Dive Into Python翻录。

With Python older than 2.7/3.1, that’s pretty much how you do it.

For newer versions, see importlib.import_module for Python 2 and and Python 3.

You can use exec if you want to as well.

Or using __import__ you can import a list of modules by doing this:

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

Ripped straight from Dive Into Python.


回答 1

对于Python 2.7和3.1及更高版本,推荐的方法是使用importlib模块:

importlib.import_module(名称,包=无)

导入模块。name参数以绝对或相对方式指定要导入的模块(例如pkg.mod或..mod)。如果使用相对术语指定名称,则必须将package参数设置为充当解析包名称的定位符的包的名称(例如import_module(’.. mod’,’pkg.subpkg’)将导入pkg.mod)。

例如

my_module = importlib.import_module('os.path')

The recommended way for Python 2.7 and 3.1 and later is to use importlib module:

importlib.import_module(name, package=None)

Import a module. The name argument specifies what module to import in absolute or relative terms (e.g. either pkg.mod or ..mod). If the name is specified in relative terms, then the package argument must be set to the name of the package which is to act as the anchor for resolving the package name (e.g. import_module(‘..mod’, ‘pkg.subpkg’) will import pkg.mod).

e.g.

my_module = importlib.import_module('os.path')

回答 2

注意:自Python 3.4以来不推荐使用imp,而建议使用importlib

如前所述,imp模块为您提供了加载功能:

imp.load_source(name, path)
imp.load_compiled(name, path)

我以前用这些来执行类似的操作。

在我的情况下,我使用所需的定义方法定义了一个特定的类。加载模块后,我将检查该类是否在模块中,然后创建该类的实例,如下所示:

import imp
import os

def load_from_file(filepath):
    class_inst = None
    expected_class = 'MyClass'

    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    if file_ext.lower() == '.py':
        py_mod = imp.load_source(mod_name, filepath)

    elif file_ext.lower() == '.pyc':
        py_mod = imp.load_compiled(mod_name, filepath)

    if hasattr(py_mod, expected_class):
        class_inst = getattr(py_mod, expected_class)()

    return class_inst

Note: imp is deprecated since Python 3.4 in favor of importlib

As mentioned the imp module provides you loading functions:

imp.load_source(name, path)
imp.load_compiled(name, path)

I’ve used these before to perform something similar.

In my case I defined a specific class with defined methods that were required. Once I loaded the module I would check if the class was in the module, and then create an instance of that class, something like this:

import imp
import os

def load_from_file(filepath):
    class_inst = None
    expected_class = 'MyClass'

    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    if file_ext.lower() == '.py':
        py_mod = imp.load_source(mod_name, filepath)

    elif file_ext.lower() == '.pyc':
        py_mod = imp.load_compiled(mod_name, filepath)

    if hasattr(py_mod, expected_class):
        class_inst = getattr(py_mod, expected_class)()

    return class_inst

回答 3

使用imp模块或更直接的__import__()功能。

Use the imp module, or the more direct __import__() function.


回答 4

现在,您应该使用importlib

导入源文件

文档实际上提供了一个配方,它像这样:

import sys
import importlib.util

file_path = 'pluginX.py'
module_name = 'pluginX'

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(module)

导入包裹

实际上,在当前目录下导入包(例如pluginX/__init__.py)非常简单:

import importlib

pkg = importlib.import_module('pluginX')

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(pkg)

Nowadays you should use importlib.

Import a source file

The docs actually provide a recipe for that, and it goes like:

import sys
import importlib.util

file_path = 'pluginX.py'
module_name = 'pluginX'

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(module)

Import a package

Importing a package (e.g., pluginX/__init__.py) under your current dir is actually straightforward:

import importlib

pkg = importlib.import_module('pluginX')

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(pkg)

回答 5

如果您想在本地人中使用它:

>>> mod = 'sys'
>>> locals()['my_module'] = __import__(mod)
>>> my_module.version
'2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]'

同样可以使用 globals()

If you want it in your locals:

>>> mod = 'sys'
>>> locals()['my_module'] = __import__(mod)
>>> my_module.version
'2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]'

same would work with globals()


回答 6

您可以使用exec

exec("import myapp.commands.%s" % command)

You can use exec:

exec("import myapp.commands.%s" % command)

回答 7

与@monkut的解决方案类似,但在http://stamat.wordpress.com/dynamic-module-import-in-python/中描述了可重用和容错的功能:

import os
import imp

def importFromURI(uri, absl):
    mod = None
    if not absl:
        uri = os.path.normpath(os.path.join(os.path.dirname(__file__), uri))
    path, fname = os.path.split(uri)
    mname, ext = os.path.splitext(fname)

    if os.path.exists(os.path.join(path,mname)+'.pyc'):
        try:
            return imp.load_compiled(mname, uri)
        except:
            pass
    if os.path.exists(os.path.join(path,mname)+'.py'):
        try:
            return imp.load_source(mname, uri)
        except:
            pass

    return mod

Similar as @monkut ‘s solution but reusable and error tolerant described here http://stamat.wordpress.com/dynamic-module-import-in-python/:

import os
import imp

def importFromURI(uri, absl):
    mod = None
    if not absl:
        uri = os.path.normpath(os.path.join(os.path.dirname(__file__), uri))
    path, fname = os.path.split(uri)
    mname, ext = os.path.splitext(fname)

    if os.path.exists(os.path.join(path,mname)+'.pyc'):
        try:
            return imp.load_compiled(mname, uri)
        except:
            pass
    if os.path.exists(os.path.join(path,mname)+'.py'):
        try:
            return imp.load_source(mname, uri)
        except:
            pass

    return mod

回答 8

以下内容对我有用:

>>>import imp; 
>>>fp, pathname, description = imp.find_module("/home/test_module"); 
>>>test_module = imp.load_module("test_module", fp, pathname, description);
>>>print test_module.print_hello();

如果要导入shell脚本:

python -c '<above entire code in one line>'

The below piece worked for me:

>>>import imp; 
>>>fp, pathname, description = imp.find_module("/home/test_module"); 
>>>test_module = imp.load_module("test_module", fp, pathname, description);
>>>print test_module.print_hello();

if you want to import in shell-script:

python -c '<above entire code in one line>'

回答 9

例如,我的模块名称类似于jan_module/ feb_module/ mar_module

month = 'feb'
exec 'from %s_module import *'%(month)

For example, my module names are like jan_module/feb_module/mar_module.

month = 'feb'
exec 'from %s_module import *'%(month)

回答 10

以下为我工作:

import sys, glob
sys.path.append('/home/marc/python/importtest/modus')
fl = glob.glob('modus/*.py')
modulist = []
adapters=[]
for i in range(len(fl)):
    fl[i] = fl[i].split('/')[1]
    fl[i] = fl[i][0:(len(fl[i])-3)]
    modulist.append(getattr(__import__(fl[i]),fl[i]))
    adapters.append(modulist[i]())

它从文件夹“ modus”加载模块。模块具有与模块名称相同名称的单个类。例如,文件modus / modu1.py包含:

class modu1():
    def __init__(self):
        self.x=1
        print self.x

结果是动态加载的类“适配器”的列表。

The following worked for me:

import sys, glob
sys.path.append('/home/marc/python/importtest/modus')
fl = glob.glob('modus/*.py')
modulist = []
adapters=[]
for i in range(len(fl)):
    fl[i] = fl[i].split('/')[1]
    fl[i] = fl[i][0:(len(fl[i])-3)]
    modulist.append(getattr(__import__(fl[i]),fl[i]))
    adapters.append(modulist[i]())

It loads modules from the folder ‘modus’. The modules have a single class with the same name as the module name. E.g. the file modus/modu1.py contains:

class modu1():
    def __init__(self):
        self.x=1
        print self.x

The result is a list of dynamically loaded classes “adapters”.


我应该针对Python中的错误/非法参数组合引发哪个异常?

问题:我应该针对Python中的错误/非法参数组合引发哪个异常?

我想知道在Python中指示无效参数组合的最佳做法。我遇到过几种情况,其中您具有如下功能:

def import_to_orm(name, save=False, recurse=False):
    """
    :param name: Name of some external entity to import.
    :param save: Save the ORM object before returning.
    :param recurse: Attempt to import associated objects as well. Because you
        need the original object to have a key to relate to, save must be
        `True` for recurse to be `True`.
    :raise BadValueError: If `recurse and not save`.
    :return: The ORM object.
    """
    pass

唯一令人烦恼的是,每个包装都有自己的包装,通常略有不同BadValueError。我知道在Java中存在java.lang.IllegalArgumentException-是否众所周知每个人都将BadValueError在Python中创建自己的s还是存在另一种首选方法?

I was wondering about the best practices for indicating invalid argument combinations in Python. I’ve come across a few situations where you have a function like so:

def import_to_orm(name, save=False, recurse=False):
    """
    :param name: Name of some external entity to import.
    :param save: Save the ORM object before returning.
    :param recurse: Attempt to import associated objects as well. Because you
        need the original object to have a key to relate to, save must be
        `True` for recurse to be `True`.
    :raise BadValueError: If `recurse and not save`.
    :return: The ORM object.
    """
    pass

The only annoyance with this is that every package has its own, usually slightly differing BadValueError. I know that in Java there exists java.lang.IllegalArgumentException — is it well understood that everybody will be creating their own BadValueErrors in Python or is there another, preferred method?


回答 0

我只会提出ValueError,除非您需要更具体的exceptions。

def import_to_orm(name, save=False, recurse=False):
    if recurse and not save:
        raise ValueError("save must be True if recurse is True")

这样做真的没有意义class BadValueError(ValueError):pass-您的自定义类的用法与ValueError相同,那么为什么不使用它呢?

I would just raise ValueError, unless you need a more specific exception..

def import_to_orm(name, save=False, recurse=False):
    if recurse and not save:
        raise ValueError("save must be True if recurse is True")

There’s really no point in doing class BadValueError(ValueError):pass – your custom class is identical in use to ValueError, so why not use that?


回答 1

我会继承 ValueError

class IllegalArgumentError(ValueError):
    pass

有时最好创建自己的异常,但要从内置异常中继承,该异常应尽可能接近您想要的异常。

如果需要捕获该特定错误,请使用一个名称。

I would inherit from ValueError

class IllegalArgumentError(ValueError):
    pass

It is sometimes better to create your own exceptions, but inherit from a built-in one, which is as close to what you want as possible.

If you need to catch that specific error, it is helpful to have a name.


回答 2

我认为处理此问题的最佳方法是python本身处理它的方法。Python引发TypeError。例如:

$ python -c 'print(sum())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0

我们的初级开发人员刚刚在Google搜索“ python异常错误参数”中找到了此页面,而令我惊讶的是,自问这个问题以来,十年来从未出现过明显的(对我而言)答案。

I think the best way to handle this is the way python itself handles it. Python raises a TypeError. For example:

$ python -c 'print(sum())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0

Our junior dev just found this page in a google search for “python exception wrong arguments” and I’m surprised that the obvious (to me) answer wasn’t ever suggested in the decade since this question was asked.


回答 3

我几乎只看到ValueError过这种情况下使用的内建函数。

I’ve mostly just seen the builtin ValueError used in this situation.


回答 4

这取决于参数的问题。

如果参数的类型错误,则引发TypeError。例如,当您获取字符串而不是这些布尔值之一时。

if not isinstance(save, bool):
    raise TypeError(f"Argument save must be of type bool, not {type(save)}")

但是请注意,在Python中我们很少进行此类检查。如果参数确实无效,那么一些更深层的功能可能会为我们带来麻烦。而且,如果我们仅检查布尔值,也许某些代码用户以后会向其提供一个字符串,因为它知道非空字符串始终为True。这可能会救他一个演员。

如果参数包含无效值,请引发ValueError。这似乎更适合您的情况:

if recurse and not save:
    raise ValueError("If recurse is True, save should be True too")

或在此特定情况下,递归的True值表示保存的True值。由于我认为这是从错误中恢复,因此您可能还希望在日志中抱怨。

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True

It depends on what the problem with the arguments is.

If the argument has the wrong type, raise a TypeError. For example, when you get a string instead of one of those Booleans.

if not isinstance(save, bool):
    raise TypeError(f"Argument save must be of type bool, not {type(save)}")

Note, however, that in Python we rarely make any checks like this. If the argument really is invalid, some deeper function will probably do the complaining for us. And if we only check the boolean value, perhaps some code user will later just feed it a string knowing that non-empty strings are always True. It might save him a cast.

If the arguments have invalid values, raise ValueError. This seems more appropriate in your case:

if recurse and not save:
    raise ValueError("If recurse is True, save should be True too")

Or in this specific case, have a True value of recurse imply a True value of save. Since I would consider this a recovery from an error, you might also want to complain in the log.

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True

回答 5

我不确定我是否同意继承ValueError-我对文档的解释ValueError应由内建函数引发…从中继承或自己引发它似乎不正确。

当内置操作或函数接收到类型正确但值不合适的参数时引发,并且这种情况没有通过诸如IndexError之类的更精确的异常描述。

ValueError异常文档

I’m not sure I agree with inheritance from ValueError — my interpretation of the documentation is that ValueError is only supposed to be raised by builtins… inheriting from it or raising it yourself seems incorrect.

Raised when a built-in operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception such as IndexError.

ValueError documentation


回答 6

同意Markus关于提出自己的异常的建议,但是该异常的文字应阐明问题出在参数列表中,而不是单个参数值中。我建议:

class BadCallError(ValueError):
    pass

当缺少特定调用所需的关键字参数或参数值分别有效但彼此不一致时使用。 ValueError当特定参数是正确类型但超出范围时,仍将是正确的。

这不是Python中的标准exceptions吗?

总的来说,我希望Python样式在区分函数的错误输入(调用者的错误)和函数内部的错误结果(我的错误)方面更加犀利。因此,可能还存在BadArgumentError来区分参数中的值错误和本地变量中的值错误。

Agree with Markus’ suggestion to roll your own exception, but the text of the exception should clarify that the problem is in the argument list, not the individual argument values. I’d propose:

class BadCallError(ValueError):
    pass

Used when keyword arguments are missing that were required for the specific call, or argument values are individually valid but inconsistent with each other. ValueError would still be right when a specific argument is right type but out of range.

Shouldn’t this be a standard exception in Python?

In general, I’d like Python style to be a bit sharper in distinguishing bad inputs to a function (caller’s fault) from bad results within the function (my fault). So there might also be a BadArgumentError to distinguish value errors in arguments from value errors in locals.


简短的python列表之前的惯用语法是什么?

问题:简短的python列表之前的惯用语法是什么?

list.append()是添加到列表末尾的明显选择。这是有关失踪人员的合理解释list.prepend()。假设我的清单很短并且对性能的关注可以忽略不计,

list.insert(0, x)

要么

list[0:0] = [x]

惯用的?

list.append() is the obvious choice for adding to the end of a list. Here’s a reasonable explanation for the missing list.prepend(). Assuming my list is short and performance concerns are negligible, is

list.insert(0, x)

or

list[0:0] = [x]

idiomatic?


回答 0

s.insert(0, x)形式是最常见的。

但是,无论何时看到它,都可能是时候考虑使用collections.deque而不是列表了。

The s.insert(0, x) form is the most common.

Whenever you see it though, it may be time to consider using a collections.deque instead of a list.


回答 1

如果可以使用功能性方法,则以下内容很清楚

new_list = [x] + your_list

当然,你还没有插入xyour_list,而你已经创建了一个新的列表xpreprended它。

If you can go the functional way, the following is pretty clear

new_list = [x] + your_list

Of course you haven’t inserted x into your_list, rather you have created a new list with x preprended to it.


回答 2

简短的python列表之前的惯用语法是什么?

通常,您不想在Python中重复地放在列表之前。

如果它很,并且您没有做很多…那么就可以了。

list.insert

list.insert可以采用这种方式。

list.insert(0, x)

但这是无效的,因为在Python中,a list是一个指针数组,并且Python现在必须获取列表中的每个指针并将其向下移动一个,以将指向对象的指针插入第一个插槽中,因此,这实际上仅是有效的根据您的要求列出较短的清单。

这是实现该功能的CPython源代码的一个片段-如您所见,我们从数组的末尾开始,每次插入将所有内容向下移动一位:

for (i = n; --i >= where; )
    items[i+1] = items[i];

如果您希望容器/列表能够高效地添加元素,则需要一个链表。Python有一个双向链表,可以在开头和结尾快速插入-称为a deque

deque.appendleft

A collections.deque具有列表的许多方法。list.sort是一个exceptions,deque绝对不能完全用Liskov代替list

>>> set(dir(list)) - set(dir(deque))
{'sort'}

deque还有一个appendleft方法(以及popleft)。它deque是一个双端队列和一个双向链接的列表-不管长度如何,总是需要花费相同的时间来准备某些东西。在大O表示法中,列表的O(1)与O(n)时间。这是用法:

>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])

deque.extendleft

与此相关的还有双端队列的extendleft方法,该方法反复进行:

>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])

请注意,每个元素将一次添加一个,从而有效地颠倒了它们的顺序。

listvs的表现deque

首先,我们设置一些迭代的前缀:

import timeit
from collections import deque

def list_insert_0():
    l = []
    for i in range(20):
        l.insert(0, i)

def list_slice_insert():
    l = []
    for i in range(20):
        l[:0] = [i]      # semantically same as list.insert(0, i)

def list_add():
    l = []
    for i in range(20):
        l = [i] + l      # caveat: new list each time

def deque_appendleft():
    d = deque()
    for i in range(20):
        d.appendleft(i)  # semantically same as list.insert(0, i)

def deque_extendleft():
    d = deque()
    d.extendleft(range(20)) # semantically same as deque_appendleft above

和性能:

>>> min(timeit.repeat(list_insert_0))
2.8267281929729506
>>> min(timeit.repeat(list_slice_insert))
2.5210217320127413
>>> min(timeit.repeat(list_add))
2.0641671380144544
>>> min(timeit.repeat(deque_appendleft))
1.5863927800091915
>>> min(timeit.repeat(deque_extendleft))
0.5352169770048931

双端队列更快。随着列表的增加,我希望双端队列的性能更好。如果您可以使用双端队列,则extendleft可能会以这种方式获得最佳性能。

What’s the idiomatic syntax for prepending to a short python list?

You don’t usually want to repetitively prepend to a list in Python.

If it’s short, and you’re not doing it a lot… then ok.

list.insert

The list.insert can be used this way.

list.insert(0, x)

But this is inefficient, because in Python, a list is an array of pointers, and Python must now take every pointer in the list and move it down by one to insert the pointer to your object in the first slot, so this is really only efficient for rather short lists, as you ask.

Here’s a snippet from the CPython source where this is implemented – and as you can see, we start at the end of the array and move everything down by one for every insertion:

for (i = n; --i >= where; )
    items[i+1] = items[i];

If you want a container/list that’s efficient at prepending elements, you want a linked list. Python has a doubly linked list, which can insert at the beginning and end quickly – it’s called a deque.

deque.appendleft

A collections.deque has many of the methods of a list. list.sort is an exception, making deque definitively not entirely Liskov substitutable for list.

>>> set(dir(list)) - set(dir(deque))
{'sort'}

The deque also has an appendleft method (as well as popleft). The deque is a double-ended queue and a doubly-linked list – no matter the length, it always takes the same amount of time to preprend something. In big O notation, O(1) versus the O(n) time for lists. Here’s the usage:

>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])

deque.extendleft

Also relevant is the deque’s extendleft method, which iteratively prepends:

>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])

Note that each element will be prepended one at a time, thus effectively reversing their order.

Performance of list versus deque

First we setup with some iterative prepending:

import timeit
from collections import deque

def list_insert_0():
    l = []
    for i in range(20):
        l.insert(0, i)

def list_slice_insert():
    l = []
    for i in range(20):
        l[:0] = [i]      # semantically same as list.insert(0, i)

def list_add():
    l = []
    for i in range(20):
        l = [i] + l      # caveat: new list each time

def deque_appendleft():
    d = deque()
    for i in range(20):
        d.appendleft(i)  # semantically same as list.insert(0, i)

def deque_extendleft():
    d = deque()
    d.extendleft(range(20)) # semantically same as deque_appendleft above

and performance:

>>> min(timeit.repeat(list_insert_0))
2.8267281929729506
>>> min(timeit.repeat(list_slice_insert))
2.5210217320127413
>>> min(timeit.repeat(list_add))
2.0641671380144544
>>> min(timeit.repeat(deque_appendleft))
1.5863927800091915
>>> min(timeit.repeat(deque_extendleft))
0.5352169770048931

The deque is much faster. As the lists get longer, I would expect a deque to perform even better. If you can use deque’s extendleft you’ll probably get the best performance that way.


回答 3

如果有人像我一样发现这个问题,这是我对建议方法的性能测试:

Python 2.7.8

In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop

In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop

In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop

如您所见,insert切片分配几乎是显式添加速度的两倍,并且结果非常接近。正如Raymond Hettinger指出的那样,这insert是更常见的选择,我个人更喜欢这种方式优先列出。

If someone finds this question like me, here are my performance tests of proposed methods:

Python 2.7.8

In [1]: %timeit ([1]*1000000).insert(0, 0)
100 loops, best of 3: 4.62 ms per loop

In [2]: %timeit ([1]*1000000)[0:0] = [0]
100 loops, best of 3: 4.55 ms per loop

In [3]: %timeit [0] + [1]*1000000
100 loops, best of 3: 8.04 ms per loop

As you can see, insert and slice assignment are as almost twice as fast than explicit adding and are very close in results. As Raymond Hettinger noted insert is more common option and I, personally prefer this way to prepend to list.