分类目录归档:知识问答

sys.stdout.write和print之间的区别?

问题:sys.stdout.write和print之间的区别?

在某些情况下 sys.stdout.write()更好的print

示例:更好的性能;更有意义的代码)

Are there situations in which sys.stdout.write() is preferable to print?

(Examples: better performance; code that makes more sense)


回答 0

print只是一个薄包装器,用于格式化输入(可修改,但默认情况下在args和换行符之间使用空格),并调用给定对象的write函数。默认情况下,此对象为sys.stdout,但是您可以使用“雪佛龙”格式传递文件。例如:

print >> open('file.txt', 'w'), 'Hello', 'World', 2+3

参见:https : //docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement


在Python 3.x中,print成为一个功能,但它仍然有可能通过比其他一些sys.stdout感谢file的说法。

print('Hello', 'World', 2+3, file=open('file.txt', 'w'))

参见https://docs.python.org/3/library/functions.html#print


在Python 2.6+中,print它仍然是一条语句,但可以将其用作

from __future__ import print_function

更新:Bakuriu指出要指出,print函数和print语句之间(并且更一般地,函数和语句之间)存在很小的差异。

评估参数时出现错误:

print "something", 1/0, "other" #prints only something because 1/0 raise an Exception

print("something", 1/0, "other") #doesn't print anything. The function is not called

print is just a thin wrapper that formats the inputs (modifiable, but by default with a space between args and newline at the end) and calls the write function of a given object. By default this object is sys.stdout, but you can pass a file using the “chevron” form. For example:

print >> open('file.txt', 'w'), 'Hello', 'World', 2+3

See: https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement


In Python 3.x, print becomes a function, but it is still possible to pass something other than sys.stdout thanks to the fileargument.

print('Hello', 'World', 2+3, file=open('file.txt', 'w'))

See https://docs.python.org/3/library/functions.html#print


In Python 2.6+, print is still a statement, but it can be used as a function with

from __future__ import print_function

Update: Bakuriu commented to point out that there is a small difference between the print function and the print statement (and more generally between a function and a statement).

In case of an error when evaluating arguments:

print "something", 1/0, "other" #prints only something because 1/0 raise an Exception

print("something", 1/0, "other") #doesn't print anything. The function is not called

回答 1

print首先将对象转换为字符串(如果还不是字符串)。如果它不是行的开头,而不是换行符,它将在对象之前放置一个空格。

使用时 stdout,您需要自己将对象转换为字符串(例如,通过调用“ str”),并且没有换行符。

所以

print 99

等效于:

import sys
sys.stdout.write(str(99) + '\n')

print first converts the object to a string (if it is not already a string). It will also put a space before the object if it is not the start of a line and a newline character at the end.

When using stdout, you need to convert the object to a string yourself (by calling “str”, for example) and there is no newline character.

So

print 99

is equivalent to:

import sys
sys.stdout.write(str(99) + '\n')

回答 2

我的问题是,是否存在 sys.stdout.write()print

前几天完成脚本开发后,我将其上传到了UNIX服务器。我所有的调试消息都使用了print语句,但这些语句出现在服务器日志中。

在这种情况下,您可能需要sys.stdout.write代替。

My question is whether or not there are situations in which sys.stdout.write() is preferable to print

After finishing developing a script the other day, I uploaded it to a unix server. All my debug messages used print statements, and these do not appear on a server log.

This is a case where you may need sys.stdout.write instead.


回答 3

这是基于Mark Lutz 的《Learning Python》一书的一些示例代码,它解决了您的问题:

import sys
temp = sys.stdout                 # store original stdout object for later
sys.stdout = open('log.txt', 'w') # redirect all prints to this log file
print("testing123")               # nothing appears at interactive prompt
print("another line")             # again nothing appears. it's written to log file instead
sys.stdout.close()                # ordinary file object
sys.stdout = temp                 # restore print commands to interactive prompt
print("back to normal")           # this shows up in the interactive prompt

在文本编辑器中打开log.txt将显示以下内容:

testing123
another line

Here’s some sample code based on the book Learning Python by Mark Lutz that addresses your question:

import sys
temp = sys.stdout                 # store original stdout object for later
sys.stdout = open('log.txt', 'w') # redirect all prints to this log file
print("testing123")               # nothing appears at interactive prompt
print("another line")             # again nothing appears. it's written to log file instead
sys.stdout.close()                # ordinary file object
sys.stdout = temp                 # restore print commands to interactive prompt
print("back to normal")           # this shows up in the interactive prompt

Opening log.txt in a text editor will reveal the following:

testing123
another line

回答 4

至少有一种情况需要sys.stdout打印而不是打印。

如果您想覆盖一行而不转到下一行,例如在绘制进度条或状态消息时,则需要遍历以下内容

Note carriage return-> "\rMy Status Message: %s" % progress

而且由于print添加了换行符,因此最好使用sys.stdout

There’s at least one situation in which you want sys.stdout instead of print.

When you want to overwrite a line without going to the next line, for instance while drawing a progress bar or a status message, you need to loop over something like

Note carriage return-> "\rMy Status Message: %s" % progress

And since print adds a newline, you are better off using sys.stdout.


回答 5

我的问题是,是否存在sys.stdout.write()print

如果您正在编写一个可以同时写入文件和stdout的命令行应用程序,那么它将非常方便。您可以执行以下操作:

def myfunc(outfile=None):
    if outfile is None:
        out = sys.stdout
    else:
        out = open(outfile, 'w')
    try:
        # do some stuff
        out.write(mytext + '\n')
        # ...
    finally:
        if outfile is not None:
            out.close()

这确实意味着您无法使用该with open(outfile, 'w') as out:模式,但有时值得。

My question is whether or not there are situations in which sys.stdout.write() is preferable to print

If you’re writing a command line application that can write to both files and stdout then it is handy. You can do things like:

def myfunc(outfile=None):
    if outfile is None:
        out = sys.stdout
    else:
        out = open(outfile, 'w')
    try:
        # do some stuff
        out.write(mytext + '\n')
        # ...
    finally:
        if outfile is not None:
            out.close()

It does mean you can’t use the with open(outfile, 'w') as out: pattern, but sometimes it is worth it.


回答 6

在2.x中,该print语句将对您提供的内容进行预处理,将其转换为字符串,处理分隔符和换行符,并允许重定向至文件。3.x将其转换为功能,但仍具有相同的职责。

sys.stdout 是一个文件或类似文件的文件,具有用于写入文件的方法,该方法沿该行使用字符串或其他内容。

In 2.x, the print statement preprocesses what you give it, turning it into strings along the way, handling separators and newlines, and allowing redirection to a file. 3.x turns it into a function, but it still has the same responsibilities.

sys.stdout is a file or file-like that has methods for writing to it which take strings or something along that line.


回答 7

当动态打印很有用时,例如在较长的过程中提供信息,则最好:

import time, sys
Iterations = 555
for k in range(Iterations+1):
    # some code to execute here ...
    percentage = k / Iterations
    time_msg = "\rRunning Progress at {0:.2%} ".format(percentage)
    sys.stdout.write(time_msg)
    sys.stdout.flush()
    time.sleep(0.01)

it is preferable when dynamic printing is useful, for instance, to give information in a long process:

import time, sys
Iterations = 555
for k in range(Iterations+1):
    # some code to execute here ...
    percentage = k / Iterations
    time_msg = "\rRunning Progress at {0:.2%} ".format(percentage)
    sys.stdout.write(time_msg)
    sys.stdout.flush()
    time.sleep(0.01)

回答 8

>>> sys.stdout.write(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected a string or other character buffer object
>>> sys.stdout.write("a")
a>>> sys.stdout.write("a") ; print(1)
a1

观察上面的示例:

  1. sys.stdout.write不会写非字符串对象,但是print

  2. sys.stdout.write不会在结尾处添加一个新行标志,但print

如果我们深入潜水,

sys.stdout 是一个文件对象,可用于输出print()

如果print()未指定的文件参数,sys.stdout则将使用

>>> sys.stdout.write(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected a string or other character buffer object
>>> sys.stdout.write("a")
a>>> sys.stdout.write("a") ; print(1)
a1

Observing the example above:

  1. sys.stdout.write won’t write non-string object, but print will

  2. sys.stdout.write won’t add a new line symbol in the end, but print will

If we dive deeply,

sys.stdout is a file object which can be used for the output of print()

if file argument of print() is not specified, sys.stdout will be used


回答 9

在某些情况下,sys.stdout.write()更适合打印吗?

例如,我正在研究一个小的函数,该函数在将数字作为参数传递时以金字塔格式打印星星,尽管您可以使用end =“”在单独的行中打印来完成此操作,但我使用sys.stdout.write来进行协调与印刷使这项工作。要详细说明此stdout.write,请在同一行中打印,因为print总是在单独的行中打印其内容。

import sys

def printstars(count):

    if count >= 1:
        i = 1
        while (i <= count):
            x=0
            while(x<i):
                sys.stdout.write('*')
                x = x+1
            print('')
            i=i+1

printstars(5)

Are there situations in which sys.stdout.write() is preferable to print?

For example I’m working on small function which prints stars in pyramid format upon passing the number as argument, although you can accomplish this using end=”” to print in a separate line, I used sys.stdout.write in co-ordination with print to make this work. To elaborate on this stdout.write prints in the same line where as print always prints its contents in a separate line.

import sys

def printstars(count):

    if count >= 1:
        i = 1
        while (i <= count):
            x=0
            while(x<i):
                sys.stdout.write('*')
                x = x+1
            print('')
            i=i+1

printstars(5)

回答 10

在某些情况下,sys.stdout.write()更适合打印吗?

我发现在多线程情况下stdout比打印效果更好。我使用队列(FIFO)存储要打印的行,并且在打印行之前保留所有线程,直到我的打印Q为空。即使这样,使用print有时也会在调试I / O上丢失最后的\ n(使用wing pro IDE)。

当我在字符串中使用\ n的std.out时,调试I / O格式正确,并且\ n正确显示。

Are there situations in which sys.stdout.write() is preferable to print?

I have found that stdout works better than print in a multithreading situation. I use Queue (FIFO) to store the lines to print and I hold all threads before the print line until my print Q is empty. Even so, using print I sometimes lose the final \n on the debug I/O (using wing pro IDE).

When I use std.out with \n in the string the debug I/O formats correctly and the \n’s are accurately displayed.


回答 11

在Python 3中,有使用print over的正当理由sys.stdout.write,但是这个原因也可以转化为使用原因sys.stdout.write

这是因为,现在print是Python 3中的一个函数,您可以重写它。因此,您可以在简单的脚本中的任何地方使用print,并确定需要写入的那些print语句stderr。现在,您可以重新定义打印功能,甚至可以通过使用内置模块来更改打印功能来全局更改它。当然,file.write您可以指定什么文件,但是通过覆盖打印,您还可以重新定义行分隔符或参数分隔符。

另一种方法是。也许您绝对确定要写信给stdout,但也知道要将print更改为其他内容,可以决定使用sys.stdout.write,并将print用于错误日志或其他内容。

因此,您使用什么取决于您打算如何使用它。print更加灵活,但这可能是使用和不使用它的原因。我仍然会选择灵活性,然后选择打印。print代替使用的另一个原因是熟悉度。现在,更多的人会通过印刷品了解您的意思,而很少了解sys.stdout.write

In Python 3 there is valid reason to use print over sys.stdout.write, but this reason can also be turned into a reason to use sys.stdout.write instead.

This reason is that, now print is a function in Python 3, you can override this. So you can use print everywhere in a simple script and decide those print statements need to write to stderr instead. You can now just redefine the print function, you could even change the print function global by changing it using the builtins module. Off course with file.write you can specify what file is, but with overwriting print you can also redefine the line separator, or argument separator.

The other way around is. Maybe you are absolutely certain you write to stdout, but also know you are going to change print to something else, you can decide to use sys.stdout.write, and use print for error log or something else.

So, what you use depends on how you intend to use it. print is more flexible, but that can be a reason to use and to not use it. I would still opt for flexibility instead, and choose print. Another reason to use print instead is familiarity. More people will now what you mean by print and less know sys.stdout.write.


回答 12

尝试将字节打印成十六进制外观时,以下区别之一是。例如,我们知道,十进制值的2550xFF十六进制的外观:

val = '{:02x}'.format(255) 

sys.stdout.write(val) # prints ff2
print(val)            # prints ff

One of the difference is the following, when trying to print a byte into its hexadecimal appearance. For example, we know that decimal value of 255 is 0xFF in hexadecimal appearance:

val = '{:02x}'.format(255) 

sys.stdout.write(val) # prints ff2
print(val)            # prints ff

回答 13

在python 2中,如果您需要传递函数,则可以将os.sys.stdout.write分配给变量,则不能(在repl中)使用print进行此操作。

>import os
>>> cmd=os.sys.stdout.write
>>> cmd('hello')
hello>>> 

那按预期工作。

>>> cmd=print
  File "<stdin>", line 1
    cmd=print
            ^
SyntaxError: invalid syntax

那行不通。打印是一种神奇的功能。

In python 2 if you need to pass around a function then you can assign os.sys.stdout.write to a variable, you cannot do this (in the repl) with print.

>import os
>>> cmd=os.sys.stdout.write
>>> cmd('hello')
hello>>> 

That works as expected.

>>> cmd=print
  File "<stdin>", line 1
    cmd=print
            ^
SyntaxError: invalid syntax

That does not work. print is a magical function.


回答 14

在Python 3中要指出的print和之间的区别sys.stdout.write也是在终端中执行时返回的值。在Python 3中,sys.stdout.write返回字符串的长度,而print仅返回None

因此,例如,在终端中以交互方式运行以下代码将打印出字符串,然后打印其长度,因为在交互运行时将返回并输出长度:

>>> sys.stdout.write(" hi ")
 hi 4

A difference between print and sys.stdout.write to point out in Python 3, is also the value which is returned when executed in terminal. In Python 3 sys.stdout.write returns the lenght of the string whereas print returns just None.

So for example running following code interactively in the terminal would print out the string followed by its lenght, since the lenght is returned and outputed when run interactively:

>>> sys.stdout.write(" hi ")
 hi 4

如何编写Python模块/软件包?

问题:如何编写Python模块/软件包?

我一直在为工作中的简单任务制作Python脚本,从来没有真正打扰过将它们打包供其他人使用。现在,我被分配为REST API制作Python包装器。我对如何开始一无所知,我需要帮助。

我有的:

(只想尽可能地具体一点)我已经准备好virtualenv,它也位于github上,还存在用于python的.gitignore文件,以及用于与REST API交互的请求库。而已。

这是当前目录树

.
├── bin
   └── /the usual stuff/
├── include
   └── /the usual stuff/
├── lib
   └── python2.7
       └── /the usual stuff/
├── local
   └── /the usual stuff/
└── README.md

27 directories, 280 files

我什至不知道将.py文件放在哪里。

我想做的是:

使用“ pip install …”制作可安装的python模块

如果可能的话,我需要一个逐步的编写Python模块的逐步过程。

I’ve been making Python scripts for simple tasks at work and never really bothered packaging them for others to use. Now I have been assigned to make a Python wrapper for a REST API. I have absolutely no idea on how to start and I need help.

What I have:

(Just want to be specific as possible) I have the virtualenv ready, it’s also up in github, the .gitignore file for python is there as well, plus, the requests library for interacting with the REST API. That’s it.

Here’s the current directory tree

.
├── bin
│   └── /the usual stuff/
├── include
│   └── /the usual stuff/
├── lib
│   └── python2.7
│       └── /the usual stuff/
├── local
│   └── /the usual stuff/
└── README.md

27 directories, 280 files

I don’t even know where to put the .py files, if I ever make one.

What I wanted to do:

Make a python module install-able with “pip install …”

If possible, I want a general step by step process on writing Python modules.


回答 0

模块是包含Python定义和语句的文件。文件名是带有后缀的模块名称.py

创建hello.py然后编写以下函数作为其内容:

def helloworld():
   print "hello"

然后,您可以导入hello

>>> import hello
>>> hello.helloworld()
'hello'
>>>

要对许多.py文件进行分组,请将它们放在文件夹中。带有的任何文件夹__init__.py都被python视为模块,您可以将其称为包

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

您可以按照通常的方式在模块上使用import语句。

有关更多信息,请参见6.4。包

A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py

create hello.py then write the following function as its content:

def helloworld():
   print "hello"

Then you can import hello:

>>> import hello
>>> hello.helloworld()
'hello'
>>>

To group many .py files put them in a folder. Any folder with an __init__.py is considered a module by python and you can call them a package

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

You can go about with the import statement on your module the usual way.

For more information, see 6.4. Packages.


回答 1

Python 3-更新于2015年11月18日

认为已接受的答案很有用,但希望根据我自己的经验在几个方面进行扩展,以使他人受益。

模块:模块是包含Python定义和语句的文件。文件名是模块名称,后缀.py。

模块示例:假设我们在当前目录中只有一个python脚本,在这里我将其称为mymodule.py

文件mymodule.py包含以下代码:

def myfunc():
    print("Hello!")

如果我们从当前目录运行python3解释器,则可以通过以下不同方式导入和运行函数myfunc(通常,您只需选择以下一种):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

好的,这很容易。

现在假设您需要将该模块放入其自己的专用文件夹中以提供模块命名空间,而不是仅从当前工作目录中临时运行它。这是值得解释软件包概念的地方。

:包是通过使用“点分模块名称”来构造Python模块命名空间的一种方式。例如,模块名称AB在名为A的包中指定了一个名为B的子模块。就像使用模块使不同模块的作者免于担心彼此的全局变量名一样,使用带点划线的模块名称也节省了作者诸如NumPy或Python Imaging Library之类的多模块软件包,而不必担心彼此的模块名称。

包示例:现在假设我们具有以下文件夹和文件。在这里,mymodule.py与以前相同,并且__init__.py是一个空文件:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

__init__.py文件是使Python将目录视为包含包的必需文件。有关更多信息,请参见稍后提供的模块文档链接。

我们当前的工作目录位于名为mypackage的普通文件夹之上的一级

$ ls
mypackage

如果现在运行python3解释器,则可以通过以下不同方式导入并运行包含所需函数myfunc的模块mymodule.py(通常,您只需选择以下一种):

>>> import mypackage
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> import mypackage.mymodule
>>> mypackage.mymodule.myfunc()
Hello!
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mypackage.mymodule import myfunc
>>> myfunc()
Hello!
>>> from mypackage.mymodule import *
>>> myfunc()
Hello!

假设使用Python 3,以下位置提供了出色的文档:模块

关于程序包和模块的命名约定,PEP-0008中给出了通用准则-请参阅程序包和模块名称

模块应使用简短的全小写名称。如果模块名称可以提高可读性,则可以在模块名称中使用下划线。尽管不鼓励使用下划线,但Python软件包也应使用短小写全名。

Python 3 – UPDATED 18th November 2015

Found the accepted answer useful, yet wished to expand on several points for the benefit of others based on my own experiences.

Module: A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended.

Module Example: Assume we have a single python script in the current directory, here I am calling it mymodule.py

The file mymodule.py contains the following code:

def myfunc():
    print("Hello!")

If we run the python3 interpreter from the current directory, we can import and run the function myfunc in the following different ways (you would typically just choose one of the following):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

Ok, so that was easy enough.

Now assume you have the need to put this module into its own dedicated folder to provide a module namespace, instead of just running it ad-hoc from the current working directory. This is where it is worth explaining the concept of a package.

Package: Packages are a way of structuring Python’s module namespace by using “dotted module names”. For example, the module name A.B designates a submodule named B in a package named A. Just like the use of modules saves the authors of different modules from having to worry about each other’s global variable names, the use of dotted module names saves the authors of multi-module packages like NumPy or the Python Imaging Library from having to worry about each other’s module names.

Package Example: Let’s now assume we have the following folder and files. Here, mymodule.py is identical to before, and __init__.py is an empty file:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

The __init__.py files are required to make Python treat the directories as containing packages. For further information, please see the Modules documentation link provided later on.

Our current working directory is one level above the ordinary folder called mypackage

$ ls
mypackage

If we run the python3 interpreter now, we can import and run the module mymodule.py containing the required function myfunc in the following different ways (you would typically just choose one of the following):

>>> import mypackage
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> import mypackage.mymodule
>>> mypackage.mymodule.myfunc()
Hello!
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mypackage.mymodule import myfunc
>>> myfunc()
Hello!
>>> from mypackage.mymodule import *
>>> myfunc()
Hello!

Assuming Python 3, there is excellent documentation at: Modules

In terms of naming conventions for packages and modules, the general guidelines are given in PEP-0008 – please see Package and Module Names

Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.


回答 2

由于尚无人讨论过OP的这个问题:

我想做的是:

使用“ pip install …”制作可安装的python模块

这是一个绝对的最小示例,显示了使用setuptools和准备软件包并将其上传到PyPI的基本步骤twine

这绝不能代替阅读至少本教程,它比这个非常基本的示例所涵盖的内容要多得多。

在这里,其他答案已经涵盖了创建包本身,因此,让我们假设我们已经覆盖了这一步,并且我们的项目结构如下:

.
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

为了setuptools用于打包,我们需要添加一个文件setup.py,该文件进入我们项目的根文件夹:

.
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

至少,我们为包指定元数据,setup.py如下所示:

from setuptools import setup

setup(
    name='hellostackoverflow',
    version='0.0.1',
    description='a pip-installable package example',
    license='MIT',
    packages=['hellostackoverflow'],
    author='Benjamin Gerfelder',
    author_email='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

设置好之后license='MIT',我们在项目中添加了一个副本,LICENCE.txt在reStructuredText中添加了一个自述文件,如下所示README.rst

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

此时,我们准备开始使用进行打包setuptools,如果尚未安装,可以使用以下命令进行安装pip

pip install setuptools

为了做到这一点并source distribution在项目的根文件夹中创建一个,我们setup.py从命令行调用我们,指定我们想要的sdist

python setup.py sdist

这将创建我们的分发程序包和egg-info,并导致这样的文件夹结构,我们的程序包位于dist

.
├── dist/
├── hellostackoverflow.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

至此,我们有了一个可以使用安装的软件包pip,因此从我们的项目根目录开始(假设您具有本示例中的所有命名):

pip install ./dist/hellostackoverflow-0.0.1.tar.gz

如果一切顺利,我们现在可以打开一个Python解释器,我想在项目目录之外的某个地方说以避免任何混淆,然后尝试使用新的闪亮包:

Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hellostackoverflow import hellostackoverflow
>>> hellostackoverflow.greeting()
'Hello Stack Overflow!'

现在,我们已经确认该软件包已安装并且可以正常工作,我们可以将其上传到PyPI。

由于我们不想用我们的实验污染实时存储库,因此我们为测试存储库创建一个帐户,并twine为上载过程进行安装:

pip install twine

现在我们快到了,创建帐户后,我们只需要告诉twine我们上传软件包,它将要求我们提供凭据并将软件包上传到指定的存储库:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

现在,我们可以在PyPI测试库上登录我们的帐户,惊叹我们刚上传的软件包一段时间,然后使用pip以下代码进行抓取:

pip install --index-url https://test.pypi.org/simple/ hellostackoverflow

我们可以看到,基本过程不是很复杂。正如我之前所说的,它所包含的内容远不止本文所述,因此请继续阅读本教程以获取更深入的说明。

Since nobody did cover this question of the OP yet:

What I wanted to do:

Make a python module install-able with “pip install …”

Here is an absolute minimal example, showing the basic steps of preparing and uploading your package to PyPI using setuptools and twine.

This is by no means a substitute for reading at least the tutorial, there is much more to it than covered in this very basic example.

Creating the package itself is already covered by other answers here, so let us assume we have that step covered and our project structure like this:

.
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

In order to use setuptools for packaging, we need to add a file setup.py, this goes into the root folder of our project:

.
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

At the minimum, we specify the metadata for our package, our setup.py would look like this:

from setuptools import setup

setup(
    name='hellostackoverflow',
    version='0.0.1',
    description='a pip-installable package example',
    license='MIT',
    packages=['hellostackoverflow'],
    author='Benjamin Gerfelder',
    author_email='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

Since we have set license='MIT', we include a copy in our project as LICENCE.txt, alongside a readme file in reStructuredText as README.rst:

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

At this point, we are ready to go to start packaging using setuptools, if we do not have it already installed, we can install it with pip:

pip install setuptools

In order to do that and create a source distribution, at our project root folder we call our setup.py from the command line, specifying we want sdist:

python setup.py sdist

This will create our distribution package and egg-info, and result in a folder structure like this, with our package in dist:

.
├── dist/
├── hellostackoverflow.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

At this point, we have a package we can install using pip, so from our project root (assuming you have all the naming like in this example):

pip install ./dist/hellostackoverflow-0.0.1.tar.gz

If all goes well, we can now open a Python interpreter, I would say somewhere outside our project directory to avoid any confusion, and try to use our shiny new package:

Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hellostackoverflow import hellostackoverflow
>>> hellostackoverflow.greeting()
'Hello Stack Overflow!'

Now that we have confirmed the package installs and works, we can upload it to PyPI.

Since we do not want to pollute the live repository with our experiments, we create an account for the testing repository, and install twine for the upload process:

pip install twine

Now we’re almost there, with our account created we simply tell twine to upload our package, it will ask for our credentials and upload our package to the specified repository:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

We can now log into our account on the PyPI test repository and marvel at our freshly uploaded package for a while, and then grab it using pip:

pip install --index-url https://test.pypi.org/simple/ hellostackoverflow

As we can see, the basic process is not very complicated. As I said earlier, there is a lot more to it than covered here, so go ahead and read the tutorial for more in-depth explanation.


回答 3

定义所选命令后,只需将保存的文件拖放到python程序文件中的Lib文件夹中即可。

>>> import mymodule 
>>> mymodule.myfunc()

Once you have defined your chosen commands, you can simply drag and drop the saved file into the Lib folder in your python program files.

>>> import mymodule 
>>> mymodule.myfunc()

回答 4

制作一个名为“ hello.py”的文件

如果您使用的是Python 2.x

def func():
    print "Hello"

如果您使用的是Python 3.x

def func():
    print("Hello")

运行文件。然后,您可以尝试以下操作:

>>> import hello
>>> hello.func()
Hello

如果您想稍微努力一点,可以使用以下方法:

如果您使用的是Python 2.x

def say(text):
    print text

如果您使用的是Python 3.x

def say(text):
    print(text)

看到定义旁边括号中的一个吗?那很重要。您可以在定义中使用它。

文本-​​当您希望程序说出想要的内容时可以使用它。根据其名称,它是文本。希望您知道文本的含义。它的意思是“单词”或“句子”。

运行文件。然后,如果您使用的是Python 3.x,则可以尝试以下操作:

>>> import hello
>>> hello.say("hi")
hi
>>> from hello import say
>>> say("test")
test

对于Python 2.x-我猜与Python 3相同吗?不知道。如果我在Python 2.x上犯了一个错误,请纠正我(我知道Python 2,但是我与Python 3一起使用)

Make a file named “hello.py”

If you are using Python 2.x

def func():
    print "Hello"

If you are using Python 3.x

def func():
    print("Hello")

Run the file. Then, you can try the following:

>>> import hello
>>> hello.func()
Hello

If you want a little bit hard, you can use the following:

If you are using Python 2.x

def say(text):
    print text

If you are using Python 3.x

def say(text):
    print(text)

See the one on the parenthesis beside the define? That is important. It is the one that you can use within the define.

Text – You can use it when you want the program to say what you want. According to its name, it is text. I hope you know what text means. It means “words” or “sentences”.

Run the file. Then, you can try the following if you are using Python 3.x:

>>> import hello
>>> hello.say("hi")
hi
>>> from hello import say
>>> say("test")
test

For Python 2.x – I guess same thing with Python 3? No idea. Correct me if I made a mistake on Python 2.x (I know Python 2 but I am used with Python 3)


回答 5

我创建了一个项目,以轻松地从头开始创建项目框架https://github.com/MacHu-GWU/pygitrepo-project

假设您可以创建一个测试项目learn_creating_py_package

您可以了解具有不同用途的组件,例如

  • 创建virtualenv
  • 自行安装
  • 运行单元测试
  • 运行代码覆盖率
  • 建立文件
  • 部署文件
  • 在不同的python版本中运行unittest
  • 部署到PYPI

使用的好处pygitrepo是,这些繁琐的自动创建本身和适应你package_nameproject_namegithub_accountdocument host servicewindows or macos or linux

这是学习像pro一样开发python项目的好地方。

希望这会有所帮助。

谢谢。

I created a project to easily initiate a project skeleton from scratch. https://github.com/MacHu-GWU/pygitrepo-project.

And you can create a test project, let’s say, learn_creating_py_package.

You can learn what component you should have for different purpose like:

  • create virtualenv
  • install itself
  • run unittest
  • run code coverage
  • build document
  • deploy document
  • run unittest in different python version
  • deploy to PYPI

The advantage of using pygitrepo is that those tedious are automatically created itself and adapt your package_name, project_name, github_account, document host service, windows or macos or linux.

It is a good place to learn develop a python project like a pro.

Hope this could help.

Thank you.


Python列表与数组-何时使用?

问题:Python列表与数组-何时使用?

如果要创建一维数组,则可以将其实现为列表,也可以使用标准库中的“数组”模块。我一直将列表用于一维数组。

我想改用数组模块的原因或情况是什么?

是为了性能和内存优化,还是我缺少明显的东西?

If you are creating a 1d array, you can implement it as a List, or else use the ‘array’ module in the standard library. I have always used Lists for 1d arrays.

What is the reason or circumstance where I would want to use the array module instead?

Is it for performance and memory optimization, or am I missing something obvious?


回答 0

基本上,Python列表非常灵活,可以保存完全不同的任意数据,并且可以在摊销后的固定时间内非常高效地附加到它们。如果您需要高效而又省时地缩小和扩展列表,则可以采用这些方法。但是它们比C数组占用更多的空间

array.array类型,在另一方面,是只在C数组的薄包装。它只能保存所有相同类型的同类数据,因此仅使用sizeof(one object) * length内存字节。通常,在需要将C数组公开给扩展名或系统调用(例如ioctlfctnl)时,应使用它。

array.array也是在Python 2.x()中表示可变字符串的一种合理方法array('B', bytes)。但是,Python 2.6+和3.x提供了一个可变字节字符串bytearray

但是,如果要对数字数据的均质数组进行数学运算,则最好使用NumPy,它可以自动对复杂的多维数组进行矢量化操作。

简而言之array.array当您需要除数学之外的其他原因而需要同构C数据数组时,此选项很有用。

Basically, Python lists are very flexible and can hold completely heterogeneous, arbitrary data, and they can be appended to very efficiently, in amortized constant time. If you need to shrink and grow your list time-efficiently and without hassle, they are the way to go. But they use a lot more space than C arrays.

The array.array type, on the other hand, is just a thin wrapper on C arrays. It can hold only homogeneous data, all of the same type, and so it uses only sizeof(one object) * length bytes of memory. Mostly, you should use it when you need to expose a C array to an extension or a system call (for example, ioctl or fctnl).

array.array is also a reasonable way to represent a mutable string in Python 2.x (array('B', bytes)). However, Python 2.6+ and 3.x offers a mutable byte string as bytearray.

However, if you want to do math on a homogeneous array of numeric data, then you’re much better off using NumPy, which can automatically vectorize operations on complex multi-dimensional arrays.

To make a long story short: array.array is useful when you need a homogeneous C array of data for reasons other than doing math.


回答 1

在几乎所有情况下,正常列表都是正确的选择。数组模块更像是C数组的一个薄包装器,它为您提供了一种强类型的容器(请参阅docs),可以访问更多类似C的类型,例如有符号/无符号short或double,这不是构建的一部分-in类型。我说只有在确实需要时才使用arrays模块,在所有其他情况下,都坚持使用列表。

For almost all cases the normal list is the right choice. The arrays module is more like a thin wrapper over C arrays, which give you kind of strongly typed containers (see docs), with access to more C-like types such as signed/unsigned short or double, which are not part of the built-in types. I’d say use the arrays module only if you really need it, in all other cases stick with lists.


回答 2

如果您不知道为什么要使用它,那么数组模块就是其中一种您可能不需要的东西(请注意,我并不是要以居高临下的方式来说明这一点!) 。大多数时候,数组模块用于与C代码进行接口。为您提供有关性能问题的更直接答案:

对于某些用途,数组比列表更有效。如果需要分配一个您不会更改的数组,那么数组可以更快并且使用更少的内存。GvR有一个优化轶事,其中阵列模块是赢家(长期阅读,但值得)。

另一方面,列表消耗的内存比数组多的部分原因是因为当所有分配的元素都被使用时,python将分配一些额外的元素。这意味着将项目追加到列表的速度更快。因此,如果您计划添加项目,则要使用列表。

TL; DR如果您有特殊的优化需求或需要与C代码进行接口(并且不能使用pyrex),则仅使用数组。

The array module is kind of one of those things that you probably don’t have a need for if you don’t know why you would use it (and take note that I’m not trying to say that in a condescending manner!). Most of the time, the array module is used to interface with C code. To give you a more direct answer to your question about performance:

Arrays are more efficient than lists for some uses. If you need to allocate an array that you KNOW will not change, then arrays can be faster and use less memory. GvR has an optimization anecdote in which the array module comes out to be the winner (long read, but worth it).

On the other hand, part of the reason why lists eat up more memory than arrays is because python will allocate a few extra elements when all allocated elements get used. This means that appending items to lists is faster. So if you plan on adding items, a list is the way to go.

TL;DR I’d only use an array if you had an exceptional optimization need or you need to interface with C code (and can’t use pyrex).


回答 3

这是一个权衡!

每个人的优点:

清单

  • 灵活
  • 可以是异构的

数组(例如:numpy数组)

  • 统一值数组
  • 同质
  • 紧凑(尺寸)
  • 高效(功能和速度)
  • 方便

It’s a trade off !

pros of each one :

list

  • flexible
  • can be heterogeneous

array (ex: numpy array)

  • array of uniform values
  • homogeneous
  • compact (in size)
  • efficient (functionality and speed)
  • convenient

回答 4

我的理解是,数组的存储效率更高(例如,内存的连续块与指向Python对象的指针),但是我不知道任何性能上的好处。另外,对于数组,您必须存储相同类型的原语,而列表可以存储任何内容。

My understanding is that arrays are stored more efficiently (i.e. as contiguous blocks of memory vs. pointers to Python objects), but I am not aware of any performance benefit. Additionally, with arrays you must store primitives of the same type, whereas lists can store anything.


回答 5

标准库数组对于二进制I / O很有用,例如将整数列表转换为要写入例如wave文件的字符串。也就是说,正如许多人已经指出的那样,如果您要进行任何实际工作,则应考虑使用NumPy。

The standard library arrays are useful for binary I/O, such as translating a list of ints to a string to write to, say, a wave file. That said, as many have already noted, if you’re going to do any real work then you should consider using NumPy.


回答 6

如果要使用数组,请考虑使用numpy或scipy包,它们为数组提供了更大的灵活性。

If you’re going to be using arrays, consider the numpy or scipy packages, which give you arrays with a lot more flexibility.


回答 7

数组只能用于特定类型,而列表可以用于任何对象。

数组也只能是一种类型的数据,而列表可以具有各种对象类型的条目。

数组对于某些数值计算也更加有效。

Array can only be used for specific types, whereas lists can be used for any object.

Arrays can also only data of one type, whereas a list can have entries of various object types.

Arrays are also more efficient for some numerical computation.


回答 8

numpy数组和list之间的重要区别是,数组切片是原始数组上的视图。这意味着不会复制数据,并且对视图的任何修改将反映在源数组中。

An important difference between numpy array and list is that array slices are views on the original array. This means that the data is not copied, and any modifications to the view will be reflected in the source array.


回答 9

这个答案将总结几乎所有有关何时使用List和Array的查询:

  1. 这两种数据类型之间的主要区别是可以对它们执行的操作。例如,您可以将数组除以3,然后将数组的每个元素除以3。使用列表无法完成相同的操作。

  2. 该列表是python语法的一部分,因此不需要声明它,而您必须在使用它之前声明该数组。

  3. 您可以将不同数据类型的值存储在列表中(异构),而在Array中,您只能存储相同数据类型的值(异构)。

  4. 数组具有丰富的功能和快速的功能,与列表相比,它广泛用于算术运算和存储大量数据。

  5. 与列表相比,数组占用的内存更少。

This answer will sum up almost all the queries about when to use List and Array:

  1. The main difference between these two data types is the operations you can perform on them. For example, you can divide an array by 3 and it will divide each element of array by 3. Same can not be done with the list.

  2. The list is the part of python’s syntax so it doesn’t need to be declared whereas you have to declare the array before using it.

  3. You can store values of different data-types in a list (heterogeneous), whereas in Array you can only store values of only the same data-type (homogeneous).

  4. Arrays being rich in functionalities and fast, it is widely used for arithmetic operations and for storing a large amount of data – compared to list.

  5. Arrays take less memory compared to lists.


什么时候del在python中有用?

问题:什么时候del在python中有用?

我真的想不出python为什么需要del关键字的任何原因(大多数语言似乎没有类似的关键字)。例如,可以删除变量而不是删除变量None。从字典中删除时,del可以添加一个方法。

是否有任何理由保留del在python中,或者它是Python的垃圾收集日的痕迹?

I can’t really think of any reason why python needs the del keyword (and most languages seem to not have a similar keyword). For instance, rather than deleting a variable, one could just assign None to it. And when deleting from a dictionary, a del method could be added.

Is there any reason to keep del in python, or is it a vestige of Python’s pre-garbage collection days?


回答 0

首先,除了局部变量,您还可以进行其他操作

del list_item[4]
del dictionary["alpha"]

两者都应该明显有用。其次,del在局部变量上使用可使意图更清晰。相比:

del foo

foo = None

我知道在这种情况下del foo,目的是从范围中删除变量。目前尚不清楚这样foo = None做。如果有人刚分配,foo = None我可能认为这是无效代码。但是我立即知道某个编码人员del foo正在尝试做什么。

Firstly, you can del other things besides local variables

del list_item[4]
del dictionary["alpha"]

Both of which should be clearly useful. Secondly, using del on a local variable makes the intent clearer. Compare:

del foo

to

foo = None

I know in the case of del foo that the intent is to remove the variable from scope. It’s not clear that foo = None is doing that. If somebody just assigned foo = None I might think it was dead code. But I instantly know what somebody who codes del foo was trying to do.


回答 1

这是做什么的一部分del(来自Python语言参考):

删除名称会从本地或全局命名空间中删除该名称的绑定

分配None名称不会从命名空间中删除名称的绑定。

(我想可能存在一些关于删除名称绑定是否真正有用的参数,但这是另一个问题。)

There’s this part of what del does (from the Python Language Reference):

Deletion of a name removes the binding of that name from the local or global namespace

Assigning None to a name does not remove the binding of the name from the namespace.

(I suppose there could be some debate about whether removing a name binding is actually useful, but that’s another question.)


回答 2

我发现一个del有用的地方是清理for循环中的无关变量:

for x in some_list:
  do(x)
del x

现在,您可以确定,如果在for循环之外使用x,它将是未定义的。

One place I’ve found del useful is cleaning up extraneous variables in for loops:

for x in some_list:
  do(x)
del x

Now you can be sure that x will be undefined if you use it outside the for loop.


回答 3

删除变量与将其设置为“无”不同

用删除变量名del可能很少使用,但是如果没有关键字就无法轻易实现。如果您可以通过编写来创建变量名a=1,那么理论上可以通过删除a来撤消该操作。

在某些情况下,它可以简化调试过程,因为尝试访问已删除的变量将引发NameError。

您可以删除类实例属性

Python使您可以编写如下内容:

class A(object):
    def set_a(self, a):
        self.a=a
a=A()
a.set_a(3)
if hasattr(a, "a"):
    print("Hallo")

如果您选择向类实例动态添加属性,那么您当然希望能够通过编写来撤消它

del a.a

Deleting a variable is different than setting it to None

Deleting variable names with del is probably something used rarely, but it is something that could not trivially be achieved without a keyword. If you can create a variable name by writing a=1, it is nice that you can theoretically undo this by deleting a.

It can make debugging easier in some cases as trying to access a deleted variable will raise an NameError.

You can delete class instance attributes

Python lets you write something like:

class A(object):
    def set_a(self, a):
        self.a=a
a=A()
a.set_a(3)
if hasattr(a, "a"):
    print("Hallo")

If you choose to dynamically add attributes to a class instance, you certainly want to be able to undo it by writing

del a.a

回答 4

有一个特定的示例说明您在检查异常时应使用的时间del(可能还有其他,但我知道这是sys.exc_info()一时的事)。此函数返回一个元组,引发的异常类型,消息和回溯。

前两个值通常足以诊断错误并采取措施,但第三个值包含引发异常与捕获异常之间的整个调用堆栈。特别是如果您做类似的事情

try:
    do_evil()
except:
    exc_type, exc_value, tb = sys.exc_info()
    if something(exc_value):
        raise

追溯,tb最终出现在调用堆栈的本地中,从而创建了无法进行垃圾回收的循环引用。因此,执行以下操作很重要:

try:
    do_evil()
except:
    exc_type, exc_value, tb = sys.exc_info()
    del tb
    if something(exc_value):
        raise

打破循环参考。在很多情况下,你想打电话sys.exc_info(),像元类魔术,回溯有用的,所以你必须确保你清理之前,你都不可能离开异常处理程序。如果不需要回溯,则应立即将其删除,或者直接执行以下操作:

exc_type, exc_value = sys.exc_info()[:2]

为了避免所有这一切。

There is a specific example of when you should use del (there may be others, but I know about this one off hand) when you are using sys.exc_info() to inspect an exception. This function returns a tuple, the type of exception that was raised, the message, and a traceback.

The first two values are usually sufficient to diagnose an error and act on it, but the third contains the entire call stack between where the exception was raised and where the the exception is caught. In particular, if you do something like

try:
    do_evil()
except:
    exc_type, exc_value, tb = sys.exc_info()
    if something(exc_value):
        raise

the traceback, tb ends up in the locals of the call stack, creating a circular reference that cannot be garbage collected. Thus, it is important to do:

try:
    do_evil()
except:
    exc_type, exc_value, tb = sys.exc_info()
    del tb
    if something(exc_value):
        raise

to break the circular reference. In many cases where you would want to call sys.exc_info(), like with metaclass magic, the traceback is useful, so you have to make sure that you clean it up before you can possibly leave the exception handler. If you don’t need the traceback, you should delete it immediately, or just do:

exc_type, exc_value = sys.exc_info()[:2]

To avoid it all together.


回答 5

只是另一种想法。

在像Django这样的框架中调试http应用程序时,调用堆栈充满了以前使用的无用且混乱的变量,尤其是当列表很长时,对于开发人员而言可能非常痛苦。因此,此时,命名空间控制可能会很有用。

Just another thinking.

When debugging http applications in framework like Django, the call stack full of useless and messed up variables previously used, especially when it’s a very long list, could be very painful for developers. so, at this point, namespace controlling could be useful.


回答 6

与将变量分配给None相比,显式使用“ del”也是一种更好的做法。如果尝试删除不存在的变量,则会遇到运行时错误,但如果尝试将不存在的变量设置为None,Python会静默将新变量设置为None,而将变量保留为想删除它在哪里。因此,del将帮助您尽早发现错误

Using “del” explicitly is also better practice than assigning a variable to None. If you attempt to del a variable that doesn’t exist, you’ll get a runtime error but if you attempt to set a variable that doesn’t exist to None, Python will silently set a new variable to None, leaving the variable you wanted deleted where it was. So del will help you catch your mistakes earlier


回答 7

要为以上答案添加几点: del x

x指示的定义r -> or指向对象的引用o),但del x更改r而不是o。这是对对象(而不是与关联的对象)的引用(指针)的操作x。区分ro是此处的关键。

  • 它将从中删除locals()
  • globals()如果x属于它,将其删除。
  • 将其从堆栈框架中删除(从物理上删除引用,但对象本身位于对象池中,而不位于堆栈框架中)。
  • 从当前作用域中删除它。限制局部变量定义的范围非常有用,否则会导致问题。
  • 它更多地是关于名称的声明而不是内容的定义。
  • 它影响x属于的地方,而不影响x指向的地方。内存中唯一的物理更改是这样。例如,如果x在字典或列表中,则将其(作为参考)从那里(不一定从对象池中)删除。在此示例中,它所属的字典是locals()与重叠的堆栈框架()globals()

To add a few points to above answers: del x

Definition of x indicates r -> o (a reference r pointing to an object o) but del x changes r rather than o. It is an operation on the reference (pointer) to object rather than the object associated with x. Distinguishing between r and o is key here.

  • It removes it from locals().
  • Removes it from globals() if x belongs there.
  • Removes it from the stack frame (removes the reference physically from it, but the object itself resides in object pool and not in the stack frame).
  • Removes it from the current scope. It is very useful to limit the span of definition of a local variable, which otherwise can cause problems.
  • It is more about declaration of the name rather than definition of content.
  • It affects where x belongs to, not where x points to. The only physical change in memory is this. For example if x is in a dictionary or list, it (as a reference) is removed from there(and not necessarily from the object pool). In this example, the dictionary it belongs is the stack frame (locals()), which overlaps with globals().

回答 8

使用numpy.load后强制关闭文件:

利基用法也许,但我发现它在numpy.load用于读取文件时很有用。我会不时地更新文件,并且需要将具有相同名称的文件复制到目录中。

我曾经del发布过文件,并允许我复制到新文件中。

请注意,我想避免使用with上下文管理器,因为我在命令行上玩弄图并且不想太多地按下Tab键!

看到这个问题。

Force closing a file after using numpy.load:

A niche usage perhaps but I found it useful when using numpy.load to read a file. Every once in a while I would update the file and need to copy a file with the same name to the directory.

I used del to release the file and allow me to copy in the new file.

Note I want to avoid the with context manager as I was playing around with plots on the command line and didn’t want to be pressing tab a lot!

See this question.


回答 9

del通常在__init__.py文件中看到。__init__.py文件中定义的所有全局变量都将自动“导出”(将包含在中from module import *)。避免这种情况的一种方法是定义__all__,但这会变得混乱,而且并非所有人都使用它。

例如,如果您的代码__init__.py

import sys
if sys.version_info < (3,):
    print("Python 2 not supported")

然后,您的模块将导出sys名称。你应该写

import sys
if sys.version_info < (3,):
    print("Python 2 not supported")

del sys

del is often seen in __init__.py files. Any global variable that is defined in an __init__.py file is automatically “exported” (it will be included in a from module import *). One way to avoid this is to define __all__, but this can get messy and not everyone uses it.

For example, if you had code in __init__.py like

import sys
if sys.version_info < (3,):
    print("Python 2 not supported")

Then your module would export the sys name. You should instead write

import sys
if sys.version_info < (3,):
    print("Python 2 not supported")

del sys

回答 10

作为一个例子什么del可用于,我觉得有用我的情况是这样的:

def f(a, b, c=3):
    return '{} {} {}'.format(a, b, c)

def g(**kwargs):
    if 'c' in kwargs and kwargs['c'] is None:
        del kwargs['c']

    return f(**kwargs)

# g(a=1, b=2, c=None) === '1 2 3'
# g(a=1, b=2) === '1 2 3'
# g(a=1, b=2, c=4) === '1 2 4'

这两个功能都可以在不同的封装/模块和程序员不需要知道默认值参数cf实际拥有。因此,通过将kwargs与del结合使用,可以通过将其设置为None来说“我想要c的默认值”(或者在这种情况下也可以保留它)。

您可以使用类似的方法做同样的事情:

def g(a, b, c=None):
    kwargs = {'a': a,
              'b': b}
    if c is not None:
        kwargs['c'] = c

    return f(**kwargs)

但是,我发现前面的示例更加干燥和优雅。

As an example of what del can be used for, I find it useful i situations like this:

def f(a, b, c=3):
    return '{} {} {}'.format(a, b, c)

def g(**kwargs):
    if 'c' in kwargs and kwargs['c'] is None:
        del kwargs['c']

    return f(**kwargs)

# g(a=1, b=2, c=None) === '1 2 3'
# g(a=1, b=2) === '1 2 3'
# g(a=1, b=2, c=4) === '1 2 4'

These two functions can be in different packages/modules and the programmer doesn’t need to know what default value argument c in f actually have. So by using kwargs in combination with del you can say “I want the default value on c” by setting it to None (or in this case also leave it).

You could do the same thing with something like:

def g(a, b, c=None):
    kwargs = {'a': a,
              'b': b}
    if c is not None:
        kwargs['c'] = c

    return f(**kwargs)

However I find the previous example more DRY and elegant.


回答 11

什么时候del在python中有用?

您可以使用它删除数组的单个元素,而不是切片语法x[i:i+1]=[]。例如,如果您在其中os.walk并希望删除目录中的元素,这可能会很有用。不过,我认为关键字对此无济于事,因为一个人只能制作一个[].remove(index)方法(该.remove方法实际上是搜索并删除第一个实例值)。

When is del useful in python?

You can use it to remove a single element of an array instead of the slice syntax x[i:i+1]=[]. This may be useful if for example you are in os.walk and wish to delete an element in the directory. I would not consider a keyword useful for this though, since one could just make a [].remove(index) method (the .remove method is actually search-and-remove-first-instance-of-value).


回答 12

del当使用Numpy处理大数据时,我发现对于伪手动内存管理很有用。例如:

for image_name in large_image_set:
    large_image = io.imread(image_name)
    height, width, depth = large_image.shape
    large_mask = np.all(large_image == <some_condition>)
    # Clear memory, make space
    del large_image; gc.collect()

    large_processed_image = np.zeros((height, width, depth))
    large_processed_image[large_mask] = (new_value)
    io.imsave("processed_image.png", large_processed_image)

    # Clear memory, make space
    del large_mask, large_processed_image; gc.collect()

这可能是由于Python GC无法跟上系统疯狂地交换脚本而使脚本陷入停顿状态,并且在松散的内存阈值下它可以完美平滑地运行,从而留出了很大的可用空间来浏览机器和代码,而它的工作。

I’ve found del to be useful for pseudo-manual memory management when handling large data with Numpy. For example:

for image_name in large_image_set:
    large_image = io.imread(image_name)
    height, width, depth = large_image.shape
    large_mask = np.all(large_image == <some_condition>)
    # Clear memory, make space
    del large_image; gc.collect()

    large_processed_image = np.zeros((height, width, depth))
    large_processed_image[large_mask] = (new_value)
    io.imsave("processed_image.png", large_processed_image)

    # Clear memory, make space
    del large_mask, large_processed_image; gc.collect()

This can be the difference between bringing a script to a grinding halt as the system swaps like mad when the Python GC can’t keep up, and it running perfectly smooth below a loose memory threshold that leaves plenty of headroom to use the machine to browse and code while it’s working.


回答 13

我认为del具有自己的语法的原因之一是,在某些情况下,鉴于del操作绑定或变量而不是它引用的值,用函数替换它可能很难。因此,如果要创建del的函数版本,则需要传入上下文。del foo将需要变为globals()。remove(’foo’)或locals()。remove(’foo’),从而变得混乱而且可读性较差。我仍然说,鉴于del似乎很少使用,摆脱它会很好。但是删除语言功能/缺陷可能很痛苦。也许python 4会删除它:)

I think one of the reasons that del has its own syntax is that replacing it with a function might be hard in certain cases given it operates on the binding or variable and not the value it references. Thus if a function version of del were to be created a context would need to be passed in. del foo would need to become globals().remove(‘foo’) or locals().remove(‘foo’) which gets messy and less readable. Still I say getting rid of del would be good given its seemingly rare use. But removing language features/flaws can be painful. Maybe python 4 will remove it :)


回答 14

我想详细说明可接受的答案,以突出显示将变量设置为None与使用删除变量之间的细微差别del

给定变量foo = 'bar',并提供以下函数定义:

def test_var(var):
    if var:
        print('variable tested true')
    else:
        print('variable tested false')

最初声明后,test_var(foo)Yield将variable tested true达到预期。

现在尝试:

foo = None
test_var(foo)

产生variable tested false

将此行为与:

del foo
test_var(foo)

现在提高了NameError: name 'foo' is not defined

I would like to elaborate on the accepted answer to highlight the nuance between setting a variable to None versus removing it with del:

Given the variable foo = 'bar', and the following function definition:

def test_var(var):
    if var:
        print('variable tested true')
    else:
        print('variable tested false')

Once initially declared, test_var(foo) yields variable tested true as expected.

Now try:

foo = None
test_var(foo)

which yields variable tested false.

Contrast this behavior with:

del foo
test_var(foo)

which now raises NameError: name 'foo' is not defined.


回答 15

又一小生用法:在pyroot与ROOT5或ROOT6,“删除”可以是,以去除被称为无再现有C ++对象Python对象是有用的。这允许pyroot的动态查找来找到一个同名的C ++对象,并将其绑定到python名称。因此,您可能会遇到以下情况:

import ROOT as R
input_file = R.TFile('inputs/___my_file_name___.root')
tree = input_file.Get('r')
tree.Draw('hy>>hh(10,0,5)')
R.gPad.Close()
R.hy # shows that hy is still available. It can even be redrawn at this stage.
tree.Draw('hy>>hh(3,0,3)') # overwrites the C++ object in ROOT's namespace
R.hy # shows that R.hy is None, since the C++ object it pointed to is gone
del R.hy
R.hy # now finds the new C++ object

希望此利基市场将通过ROOT7的精明对象管理而关闭。

Yet another niche usage: In pyroot with ROOT5 or ROOT6, “del” may be useful to remove a python object that referred to a no-longer existing C++ object. This allows the dynamic lookup of pyroot to find an identically-named C++ object and bind it to the python name. So you can have a scenario such as:

import ROOT as R
input_file = R.TFile('inputs/___my_file_name___.root')
tree = input_file.Get('r')
tree.Draw('hy>>hh(10,0,5)')
R.gPad.Close()
R.hy # shows that hy is still available. It can even be redrawn at this stage.
tree.Draw('hy>>hh(3,0,3)') # overwrites the C++ object in ROOT's namespace
R.hy # shows that R.hy is None, since the C++ object it pointed to is gone
del R.hy
R.hy # now finds the new C++ object

Hopefully, this niche will be closed with ROOT7’s saner object management.


回答 16

“ del”命令对于控制数组中的数据非常有用,例如:

elements = ["A", "B", "C", "D"]
# Remove first element.
del elements[:1]
print(elements)

输出:

[‘B’,’C’,’D’]

The “del” command is very useful for controlling data in an array, for example:

elements = ["A", "B", "C", "D"]
# Remove first element.
del elements[:1]
print(elements)

Output:

[‘B’, ‘C’, ‘D’]


回答 17

一旦我不得不使用:

del serial
serial = None

因为仅使用:

serial = None

释放串口的速度不够快,无法立即再次打开它。从那堂课中,我学到了del真正的意思:“现在就GC!等到完成为止”,这在很多情况下非常有用。当然,您可能会有一个system.gc.del_this_and_wait_balbalbalba(obj)

Once I had to use:

del serial
serial = None

because using only:

serial = None

didn’t release the serial port fast enough to immediately open it again. From that lesson I learned that del really meant: “GC this NOW! and wait until it’s done” and that is really useful in a lot of situations. Of course, you may have a system.gc.del_this_and_wait_balbalbalba(obj).


回答 18

del在许多语言中都等同于“未设置”,并且作为从另一种语言到python的交叉参考点。人们倾向于寻找命令,它们执行的操作与以前使用第一语言时所做的相同……将var更改为“”或没有任何操作并不会真正从范围中删除该var。它只是清空其值,该var本身的名称仍将存储在内存中…为什么?!在占用大量内存的脚本中..保持垃圾桶的“否”和“反之……”每种语言都具有某种形式的“未设置/删除” var函数..为什么不使用python?

del is the equivalent of “unset” in many languages and as a cross reference point moving from another language to python.. people tend to look for commands that do the same thing that they used to do in their first language… also setting a var to “” or none doesn’t really remove the var from scope..it just empties its value the name of the var itself would still be stored in memory…why?!? in a memory intensive script..keeping trash behind its just a no no and anyways…every language out there has some form of an “unset/delete” var function..why not python?


回答 19

python中的每个对象都有一个标识符,类型,与之关联的引用计数,当我们使用del时,引用计数会减少,当引用计数变为零时,它很可能成为垃圾回收的候选对象。与将标识符设置为“无”相比,这可以区分del。在后面的情况下,它只是意味着该对象被遗忘了(直到我们超出范围,在这种情况下,计数减少了),现在标识符仅指向其他某个对象(内存位置)。

Every object in python has an identifier, Type, reference count associated with it, when we use del the reference count is reduced, when the reference count becomes zero it is a potential candidate for getting garbage collected. This differentiates the del when compared to setting an identifier to None. In later case it simply means the object is just left out wild( until we are out of scope in which case the count is reduced) and simply now the identifier point to some other object(memory location).


Python单元测试-与assertRaises相反吗?

问题:Python单元测试-与assertRaises相反吗?

我想编写一个测试来确定在给定的情况下不引发异常。

测试是否引发异常很简单

sInvalidPath=AlwaysSuppliesAnInvalidPath()
self.assertRaises(PathIsNotAValidOne, MyObject, sInvalidPath) 

…但是你怎么做相反

像这样的东西我在追求…

sValidPath=AlwaysSuppliesAValidPath()
self.assertNotRaises(PathIsNotAValidOne, MyObject, sValidPath) 

I want to write a test to establish that an Exception is not raised in a given circumstance.

It’s straightforward to test if an Exception is raised …

sInvalidPath=AlwaysSuppliesAnInvalidPath()
self.assertRaises(PathIsNotAValidOne, MyObject, sInvalidPath) 

… but how can you do the opposite.

Something like this i what I’m after …

sValidPath=AlwaysSuppliesAValidPath()
self.assertNotRaises(PathIsNotAValidOne, MyObject, sValidPath) 

回答 0

def run_test(self):
    try:
        myFunc()
    except ExceptionType:
        self.fail("myFunc() raised ExceptionType unexpectedly!")
def run_test(self):
    try:
        myFunc()
    except ExceptionType:
        self.fail("myFunc() raised ExceptionType unexpectedly!")

回答 1

嗨-我想编写一个测试来确定在给定的情况下不引发异常。

这是默认的假设-不引发异常。

如果您什么都没说,则在每个测试中都假设了这一点。

您不必为此写任何断言。

Hi – I want to write a test to establish that an Exception is not raised in a given circumstance.

That’s the default assumption — exceptions are not raised.

If you say nothing else, that’s assumed in every single test.

You don’t have to actually write an any assertion for that.


回答 2

只需调用该函数即可。如果引发异常,则单元测试框架会将其标记为错误。您可能要添加评论,例如:

sValidPath=AlwaysSuppliesAValidPath()
# Check PathIsNotAValidOne not thrown
MyObject(sValidPath)

Just call the function. If it raises an exception, the unit test framework will flag this as an error. You might like to add a comment, e.g.:

sValidPath=AlwaysSuppliesAValidPath()
# Check PathIsNotAValidOne not thrown
MyObject(sValidPath)

回答 3

我是原始发布者,我没有在代码中首先使用它就接受了DGH的上述回答。

一旦我使用完,我意识到实际上需要做一些调整才能做我需要做的事情(为了公平对待DGH,他/她确实说了“或类似的话!”)。

我认为值得在这里发表一些调整以使他人受益:

    try:
        a = Application("abcdef", "")
    except pySourceAidExceptions.PathIsNotAValidOne:
        pass
    except:
        self.assertTrue(False)

我在这里尝试做的是确保如果尝试使用第二个空格参数实例化Application对象,则将引发pySourceAidExceptions.PathIsNotAValidOne。

我相信使用上面的代码(主要基于DGH的答案)可以做到。

I am the original poster and I accepted the above answer by DGH without having first used it in the code.

Once I did use I realised that it needed a little tweaking to actually do what I needed it to do (to be fair to DGH he/she did say “or something similar” !).

I thought it was worth posting the tweak here for the benefit of others:

    try:
        a = Application("abcdef", "")
    except pySourceAidExceptions.PathIsNotAValidOne:
        pass
    except:
        self.assertTrue(False)

What I was attempting to do here was to ensure that if an attempt was made to instantiate an Application object with a second argument of spaces the pySourceAidExceptions.PathIsNotAValidOne would be raised.

I believe that using the above code (based heavily on DGH’s answer) will do that.


回答 4

您可以定义assertNotRaises通过重用对原执行的90%assertRaises的中unittest模块。使用这种方法,最终得到的assertNotRaises方法除了其反向失败条件外,其行为与相同assertRaises

TLDR和现场演示

事实证明,向其中添加assertNotRaises方法非常容易unittest.TestCase(编写此答案所花的时间是代码的四倍,这使我花了大约四倍的时间)。这是该assertNotRaises方法的现场演示。就像一样assertRaises,您可以将callable和args传递给assertNotRaises,也可以在with语句中使用它。现场演示包括一个测试案例,演示了assertNotRaises预期的工作方式。

细节

assertRaisesin 的实现unittest相当复杂,但是通过一些巧妙的子类化,您可以覆盖和逆转其失败条件。

assertRaises是一个简短的方法,基本上只创建unittest.case._AssertRaisesContext类的实例并返回它(请参见unittest.case模块中的定义)。您可以_AssertNotRaisesContext通过继承_AssertRaisesContext并覆盖其__exit__方法来定义自己的类:

import traceback
from unittest.case import _AssertRaisesContext

class _AssertNotRaisesContext(_AssertRaisesContext):
    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is not None:
            self.exception = exc_value.with_traceback(None)

            try:
                exc_name = self.expected.__name__
            except AttributeError:
                exc_name = str(self.expected)

            if self.obj_name:
                self._raiseFailure("{} raised by {}".format(exc_name,
                    self.obj_name))
            else:
                self._raiseFailure("{} raised".format(exc_name))

        else:
            traceback.clear_frames(tb)

        return True

通常,您可以通过从中继承来定义测试用例类TestCase。如果您改为继承子类MyTestCase

class MyTestCase(unittest.TestCase):
    def assertNotRaises(self, expected_exception, *args, **kwargs):
        context = _AssertNotRaisesContext(expected_exception, self)
        try:
            return context.handle('assertNotRaises', args, kwargs)
        finally:
            context = None

现在,您所有的测试用例都将具有assertNotRaises可用的方法。

You can define assertNotRaises by reusing about 90% of the original implementation of assertRaises in the unittest module. With this approach, you end up with an assertNotRaises method that, aside from its reversed failure condition, behaves identically to assertRaises.

TLDR and live demo

It turns out to be surprisingly easy to add an assertNotRaises method to unittest.TestCase (it took me about 4 times as long to write this answer as it did the code). Here’s a live demo of the assertNotRaises method in action. Just like assertRaises, you can either pass a callable and args to assertNotRaises, or you can use it in a with statement. The live demo includes a test cases that demonstrates that assertNotRaises works as intended.

Details

The implementation of assertRaises in unittest is fairly complicated, but with a little bit of clever subclassing you can override and reverse its failure condition.

assertRaises is a short method that basically just creates an instance of the unittest.case._AssertRaisesContext class and returns it (see its definition in the unittest.case module). You can define your own _AssertNotRaisesContext class by subclassing _AssertRaisesContext and overriding its __exit__ method:

import traceback
from unittest.case import _AssertRaisesContext

class _AssertNotRaisesContext(_AssertRaisesContext):
    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is not None:
            self.exception = exc_value.with_traceback(None)

            try:
                exc_name = self.expected.__name__
            except AttributeError:
                exc_name = str(self.expected)

            if self.obj_name:
                self._raiseFailure("{} raised by {}".format(exc_name,
                    self.obj_name))
            else:
                self._raiseFailure("{} raised".format(exc_name))

        else:
            traceback.clear_frames(tb)

        return True

Normally you define test case classes by having them inherit from TestCase. If you instead inherit from a subclass MyTestCase:

class MyTestCase(unittest.TestCase):
    def assertNotRaises(self, expected_exception, *args, **kwargs):
        context = _AssertNotRaisesContext(expected_exception, self)
        try:
            return context.handle('assertNotRaises', args, kwargs)
        finally:
            context = None

all of your test cases will now have the assertNotRaises method available to them.


回答 5

def _assertNotRaises(self, exception, obj, attr):                                                                                                                              
     try:                                                                                                                                                                       
         result = getattr(obj, attr)                                                                                                                                            
         if hasattr(result, '__call__'):                                                                                                                                        
             result()                                                                                                                                                           
     except Exception as e:                                                                                                                                                     
         if isinstance(e, exception):                                                                                                                                           
            raise AssertionError('{}.{} raises {}.'.format(obj, attr, exception)) 

如果您需要接受参数,可以进行修改。

self._assertNotRaises(IndexError, array, 'sort')
def _assertNotRaises(self, exception, obj, attr):                                                                                                                              
     try:                                                                                                                                                                       
         result = getattr(obj, attr)                                                                                                                                            
         if hasattr(result, '__call__'):                                                                                                                                        
             result()                                                                                                                                                           
     except Exception as e:                                                                                                                                                     
         if isinstance(e, exception):                                                                                                                                           
            raise AssertionError('{}.{} raises {}.'.format(obj, attr, exception)) 

could be modified if you need to accept parameters.

call like

self._assertNotRaises(IndexError, array, 'sort')

回答 6

我发现unittest按以下步骤进行Monkey补丁很有用:

def assertMayRaise(self, exception, expr):
  if exception is None:
    try:
      expr()
    except:
      info = sys.exc_info()
      self.fail('%s raised' % repr(info[0]))
  else:
    self.assertRaises(exception, expr)

unittest.TestCase.assertMayRaise = assertMayRaise

这在测试是否存在异常时阐明了意图:

self.assertMayRaise(None, does_not_raise)

这也简化了循环测试,我经常发现自己在做:

# ValueError is raised only for op(x,x), op(y,y) and op(z,z).
for i,(a,b) in enumerate(itertools.product([x,y,z], [x,y,z])):
  self.assertMayRaise(None if i%4 else ValueError, lambda: op(a, b))

I’ve found it useful to monkey-patch unittest as follows:

def assertMayRaise(self, exception, expr):
  if exception is None:
    try:
      expr()
    except:
      info = sys.exc_info()
      self.fail('%s raised' % repr(info[0]))
  else:
    self.assertRaises(exception, expr)

unittest.TestCase.assertMayRaise = assertMayRaise

This clarifies intent when testing for the absence of an exception:

self.assertMayRaise(None, does_not_raise)

This also simplifies testing in a loop, which I often find myself doing:

# ValueError is raised only for op(x,x), op(y,y) and op(z,z).
for i,(a,b) in enumerate(itertools.product([x,y,z], [x,y,z])):
  self.assertMayRaise(None if i%4 else ValueError, lambda: op(a, b))

回答 7

如果将Exception类传递给assertRaises(),则将提供一个上下文管理器。这可以提高测试的可读性:

# raise exception if Application created with bad data
with self.assertRaises(pySourceAidExceptions.PathIsNotAValidOne):
    application = Application("abcdef", "")

这使您可以在代码中测试错误情况。

在这种情况下,您正在测试PathIsNotAValidOne当您将无效参数传递给Application构造函数时引发的。

If you pass an Exception class to assertRaises(), a context manager is provided. This can improve the readability of your tests:

# raise exception if Application created with bad data
with self.assertRaises(pySourceAidExceptions.PathIsNotAValidOne):
    application = Application("abcdef", "")

This allows you to test error cases in your code.

In this case, you are testing the PathIsNotAValidOne is raised when you pass invalid parameters to the Application constructor.


回答 8

你可以这样尝试。尝试:self.assertRaises(None,function,arg1,arg2)除外:如果不将代码放入try块,则通过,它将通过异常“ AssertionError:未引发”,测试用例将失败。测试用例将通过如果放在try块中,这是预期的行为。

you can try like that. try: self.assertRaises(None,function,arg1, arg2) except: pass if you don’t put code inside try block it will through exception’ AssertionError: None not raised ” and test case will be failed. Test case will be pass if put inside try block which is expected behaviour.


回答 9

确保对象初始化没有任何错误的一种简单方法是测试对象的类型实例。

这是一个例子:

p = SomeClass(param1=_param1_value)
self.assertTrue(isinstance(p, SomeClass))

One straight forward way to ensure the object is initialized without any error is to test the object’s type instance.

Here is an example :

p = SomeClass(param1=_param1_value)
self.assertTrue(isinstance(p, SomeClass))

如何读取没有换行符的文件?

问题:如何读取没有换行符的文件?

在Python中,调用

temp = open(filename,'r').readlines()

产生一个列表,其中每个元素都是文件中的一行。这有点愚蠢,但是仍然:readlines()还向每个元素写入换行符,这是我不希望发生的事情。

我该如何避免呢?

In Python, calling

temp = open(filename,'r').readlines()

results in a list in which each element is a line in the file. It’s a little stupid but still: readlines() also writes newline character to each element, something I do not wish to happen.

How can I avoid it?


回答 0

您可以使用读取整个文件并分割行str.splitlines

temp = file.read().splitlines()

或者,您可以手动删除换行符:

temp = [line[:-1] for line in file]

注意:仅当文件以换行符结尾时,后一种解决方案才有效,否则最后一行将丢失字符。

在大多数情况下,此假设是正确的(尤其是对于文本编辑器创建的文件,无论如何,它们通常都会添加结尾换行符)。

如果要避免这种情况,可以在文件末尾添加换行符:

with open(the_file, 'r+') as f:
    f.seek(-1, 2)  # go at the end of the file
    if f.read(1) != '\n':
        # add missing newline if not already present
        f.write('\n')
        f.flush()
        f.seek(0)
    lines = [line[:-1] for line in f]

或更简单的替代方法是strip换行符:

[line.rstrip('\n') for line in file]

甚至,尽管很难理解:

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]

这利用了以下事实:的返回值or不是布尔值,而是被评估为true或false的对象。


readlines方法实际上等效于:

def readlines(self):
    lines = []
    for line in iter(self.readline, ''):
        lines.append(line)
    return lines

# or equivalently

def readlines(self):
    lines = []
    while True:
        line = self.readline()
        if not line:
            break
        lines.append(line)
    return lines

因为readline()保留换行符也readlines()保留它。

注意:为了readlines()使writelines()方法对称,不会添加结尾换行符,因此f2.writelines(f.readlines())会生成fin 的精确副本f2

You can read the whole file and split lines using str.splitlines:

temp = file.read().splitlines()

Or you can strip the newline by hand:

temp = [line[:-1] for line in file]

Note: this last solution only works if the file ends with a newline, otherwise the last line will lose a character.

This assumption is true in most cases (especially for files created by text editors, which often do add an ending newline anyway).

If you want to avoid this you can add a newline at the end of file:

with open(the_file, 'r+') as f:
    f.seek(-1, 2)  # go at the end of the file
    if f.read(1) != '\n':
        # add missing newline if not already present
        f.write('\n')
        f.flush()
        f.seek(0)
    lines = [line[:-1] for line in f]

Or a simpler alternative is to strip the newline instead:

[line.rstrip('\n') for line in file]

Or even, although pretty unreadable:

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]

Which exploits the fact that the return value of or isn’t a boolean, but the object that was evaluated true or false.


The readlines method is actually equivalent to:

def readlines(self):
    lines = []
    for line in iter(self.readline, ''):
        lines.append(line)
    return lines

# or equivalently

def readlines(self):
    lines = []
    while True:
        line = self.readline()
        if not line:
            break
        lines.append(line)
    return lines

Since readline() keeps the newline also readlines() keeps it.

Note: for symmetry to readlines() the writelines() method does not add ending newlines, so f2.writelines(f.readlines()) produces an exact copy of f in f2.


回答 1

temp = open(filename,'r').read().split('\n')
temp = open(filename,'r').read().split('\n')

回答 2

另一个例子:

一次读取文件。从字符串结尾删除不需要的字符str.rstrip(chars)

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )

又见str.strip([chars])str.lstrip([chars])

(python> = 2.0)

another example:

Reading file one row at the time. Removing unwanted chars with from end of the string str.rstrip(chars)

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )

see also str.strip([chars]) and str.lstrip([chars])

(python >= 2.0)


回答 3

temp = open(filename,'r').read().splitlines()
temp = open(filename,'r').read().splitlines()

回答 4

我认为这是最好的选择。

temp = [line.strip() for line in file.readlines()]

I think this is the best option.

temp = [line.strip() for line in file.readlines()]

回答 5

尝试这个:

u=open("url.txt","r")  
url=u.read().replace('\n','')  
print(url)  

Try this:

u=open("url.txt","r")  
url=u.read().replace('\n','')  
print(url)  

回答 6

my_file = open("first_file.txt", "r")
for line in my_file.readlines():
    if line[-1:] == "\n":
        print(line[:-1])
    else:
        print(line)
my_file.close() 
my_file = open("first_file.txt", "r")
for line in my_file.readlines():
    if line[-1:] == "\n":
        print(line[:-1])
    else:
        print(line)
my_file.close() 

回答 7

import csv

with open(filename) as f:
    csvreader = csv.reader(f)
    for line in csvreader:
         print(line[0])
import csv

with open(filename) as f:
    csvreader = csv.reader(f)
    for line in csvreader:
         print(line[0])

回答 8

def getText():
    file=open("ex1.txt","r");

    names=file.read().split("\n");
    for x,word in enumerate(names):
        if(len(word)>=20):
            return 0;
            print "length of ",word,"is over 20"
            break;
        if(x==20):
            return 0;
            break;
    else:
        return names;


def show(names):
    for word in names:
        len_set=len(set(word))
        print word," ",len_set


for i in range(1):

    names=getText();
    if(names!=0):
        show(names);
    else:
        break;
def getText():
    file=open("ex1.txt","r");

    names=file.read().split("\n");
    for x,word in enumerate(names):
        if(len(word)>=20):
            return 0;
            print "length of ",word,"is over 20"
            break;
        if(x==20):
            return 0;
            break;
    else:
        return names;


def show(names):
    for word in names:
        len_set=len(set(word))
        print word," ",len_set


for i in range(1):

    names=getText();
    if(names!=0):
        show(names);
    else:
        break;

PyCharm中未解决的参考问题

问题:PyCharm中未解决的参考问题

我有一个目录结构

├── simulate.py
├── src
   ├── networkAlgorithm.py
   ├── ...

而且我可以使用访问网络模块sys.path.insert()

import sys
import os.path
sys.path.insert(0, "./src")
from networkAlgorithm import *

但是,pycharm抱怨它无法访问该模块。我如何教pycham解析参考文献?

在此处输入图片说明

I have a directory structure

├── simulate.py
├── src
│   ├── networkAlgorithm.py
│   ├── ...

And I can access the network module with sys.path.insert().

import sys
import os.path
sys.path.insert(0, "./src")
from networkAlgorithm import *

However, pycharm complains that it cannot access the module. How can I teach pycham to resolve the reference?

enter image description here


回答 0

手动将其添加为你所做确实这样做的一种方式,但有一个简单的方法,那就是通过简单地告诉pycharm要在添加src文件夹作为源根目录,然后添加源根你的Python路径。

这样,您就不必将代码硬编码到解释器的设置中:

  • src为源内容根:

                            在此处输入图片说明

  • 然后确保将添加源添加到您的 PYTHONPATH

在此处输入图片说明

  • 现在将解决进口问题:

                      在此处输入图片说明

这样,您可以将任何所需的内容添加为源根,一切将简单地进行。但是,如果未将其标记为源根,则会出现错误:

                                  在此处输入图片说明

毕竟,别忘了重新启动。在PyCharm菜单中,选择:文件->使缓存无效/重新启动

Manually adding it as you have done is indeed one way of doing this, but there is a simpler method, and that is by simply telling pycharm that you want to add the src folder as a source root, and then adding the sources root to your python path.

This way, you don’t have to hard code things into your interpreter’s settings:

  • Add src as a source content root:

                            enter image description here

  • Then make sure to add add sources to your PYTHONPATH:

enter image description here

  • Now imports will be resolved:

                      enter image description here

This way, you can add whatever you want as a source root, and things will simply work. If you unmarked it as a source root however, you will get an error:

                                  enter image description here

After all this don’t forget to restart. In PyCharm menu select: File –> Invalidate Caches / Restart


回答 1

  1. 检查__init__.py文件src夹文件
  2. 添加 src文件夹为源根
  3. 然后确保将添加源添加到您的 PYTHONPATH(见上文)
  4. 在PyCharm菜单中选择:File-> Invalidate Caches / Restart
  1. check for __init__.py file in src folder
  2. add the src folder as a source root
  3. Then make sure to add add sources to your PYTHONPATH (see above)
  4. in PyCharm menu select: File –> Invalidate Caches / Restart

回答 2

如果有人还在看,我尝试使用PyCharm 2016.3时,可接受的答案仍然有效。用户界面可能已更改,但选项仍然相同。

即。右键单击您的根文件夹->“标记目录为”->源根

If anyone is still looking at this, the accepted answer still works for PyCharm 2016.3 when I tried it. The UI might have changed, but the options are still the same.

ie. Right click on your root folder –> ‘Mark Directory As’ –> Source Root


回答 3

测试完所有变通办法之后,建议您Settings -> Project -> project dependencies重新看看并重新安排它们。

pycharm偏好

After testing all workarounds, i suggest you to take a look at Settings -> Project -> project dependencies and re-arrange them.

pycharm prefrence


回答 4

通常,$ PYTHONPATH用于教python解释器查找必要的模块。PyCharm需要在“首选项”中添加路径。

在此处输入图片说明


回答 5

通常,这是缺少包装的问题,只需将插入号放在未解决的参考上并按Alt+Enter以显示选项,那么您应该知道如何解决。

Generally, this is a missing package problem, just place the caret at the unresolved reference and press Alt+Enter to reveal the options, then you should know how to solve it.


回答 6

遵循接受的答案后,请执行以下操作为我解决此问题:

File→交通Settings→交通Project <your directory/project>→交通Project Dependencies

选择您的未解析导入文件所在的目录/项目,并选中相应的框以告知Pycharm该项目取决于您的其他项目。

我的文件夹层次结构与问题中的文件夹层次结构略有不同。我的就是这样

├── MyDirectory  
     └── simulate.py  
├── src  
     ├── networkAlgorithm.py  
     ├── ...

告诉Pycharm src依赖于MyDirectory我,此问题已解决!

After following the accepted answer, doing the following solved it for me:

FileSettingsProject <your directory/project>Project Dependencies

Chose the directory/project where your file that has unresolved imports resides and check the box to tell Pycharm that that project depends on your other project.

My folder hierarcy is slightly different from the one in the question. Mine is like this

├── MyDirectory  
│     └── simulate.py  
├── src  
│     ├── networkAlgorithm.py  
│     ├── ...

Telling Pycharm that src depends on MyDirectory solved the issue for me!


回答 7

尽管所有答案都确实有帮助,但是应该明确解释其中一小部分信息:

  • 本质上,具有多个分层目录的项目将作为具有某些属性的包来工作。
  • 要导入本地创建的自定义类,我们需要导航到包含.py文件的目录并创建一个__init__.py(空)文件。

之所以有帮助,是因为该文件是使Python将目录视为包含包所必需的。干杯!

Although all the answers are really helpful, there’s one tiny piece of information that should be explained explicitly:

  • Essentially, a project with multiple hierarchical directories work as a package with some attributes.
  • To import custom local created Classes, we need to navigate to the directory containing .py file and create an __init__.py (empty) file there.

Why this helps is because this file is required to make Python treat the directory as containing packages. Cheers!


回答 8

通过PyCharm安装(与Community Edition一起使用)。打开,Settings > Project > Project Interpreter然后单击下面的屏幕快照中的绿色+图标。在打开的第二个对话框中,输入软件包名称,然后单击“安装软件包”按钮。

在此处输入图片说明

Install via PyCharm (works with Community Edition). Open up Settings > Project > Project Interpreter then click the green + icon in the screenshot below. In the 2nd dialogue that opens, enter the package name and click the ‘Install Package’ button.

enter image description here


回答 9

很多时候发生的事情是没有安装插件。例如

如果您正在开发django项目,并且在pyCharm中未安装django插件,则会显示错误“未解决的引用”。请参阅:https : //www.jetbrains.com/pycharm/help/resolving-references.html

Many a times what happens is that the plugin is not installed. e.g.

If you are developing a django project and you do not have django plugin installed in pyCharm, it says error ‘unresolved reference’. Refer: https://www.jetbrains.com/pycharm/help/resolving-references.html


回答 10

请检查您是否使用了正确的解释器。我遇到错误“无法解析的参考’django’”以解决此问题,我从项目设置中更改了项目解释器(将Python 3更改为Python 2.7):选择项目,转到文件->设置->项目:->项目解释器->浏览并选择正确的版本或解释器(例如/usr/bin/python2.7)。

Please check if you are using the right interpreter that you are supposed to. I was getting error “unresolved reference ‘django’ ” to solve this I changed Project Interpreter (Changed Python 3 to Python 2.7) from project settings: Select Project, go to File -> Settings -> Project: -> Project Interpreter -> Brows and Select correct version or Interpreter (e.g /usr/bin/python2.7).


回答 11

就我而言,问题是我正在使用 Virtual environment是无法访问全局站点程序包的。因此,解释器不知道新安装的软件包。

要解决此问题,只需编辑或重新创建您的虚拟解释器,然后勾选该Inherit global site-packages选项。

在此处输入图片说明

In my case the problem was I was using Virtual environment which didn’t have access to global site-packages. Thus, the interpreter was not aware of the newly installed packages.

To resolve the issue, just edit or recreate your virtual interpreter and tick the Inherit global site-packages option.

enter image description here


回答 12

这为我工作: Top Menu -> File -> Invalidate Caches/Restart

This worked for me: Top Menu -> File -> Invalidate Caches/Restart


回答 13

在PyCharm 2019.3.1中完成。 右键单击src文件夹->“标记目录为”->单击“排除”,您的src文件夹应为蓝色。

Done in PyCharm 2019.3.1 Right-click on your src folder -> “Mark Directory as” -> Click-on “Excluded” and your src folder should be blue.


回答 14

Pycharm使用venv。在venv的控制台中,您应该显式安装软件包或进入settings -> project interpreter -> add interpreter -> inherit global site-packages

Pycharm uses venv. In the venv’s console you should install the packages explicitly or go in settings -> project interpreter -> add interpreter -> inherit global site-packages.


回答 15

在较新版本的pycharm中,您可以简单地执行以下操作:右键单击要从中导入文件的目录或python包,然后单击“将目录标记为”->“源根”

In newer versions of pycharm u can do simply by right clicking on the directory or python package from which you want to import a file, then click on ‘Mark Directory As’ -> ‘Sources Root’


回答 16

解决此问题的最简单方法是在pyCharm软件中执行以下操作:

单击:文件>设置>(项目:您的项目名称)>项目解释器>

然后单击右侧的“ +”图标以搜索所需的软件包并安装。

享受编码!

The easiest way to fix it is by doing the following in your pyCharm software:

Click on: File > Settings > (Project: your project name) > Project Interpreter >

then click on the “+” icon on the right side to search for the package you want and install it.

Enjoy coding !!!


在Python中创建日期范围

问题:在Python中创建日期范围

我想创建一个日期列表,从今天开始,然后返回任意天数,例如在我的示例中为100天。有没有比这更好的方法了?

import datetime

a = datetime.datetime.today()
numdays = 100
dateList = []
for x in range (0, numdays):
    dateList.append(a - datetime.timedelta(days = x))
print dateList

I want to create a list of dates, starting with today, and going back an arbitrary number of days, say, in my example 100 days. Is there a better way to do it than this?

import datetime

a = datetime.datetime.today()
numdays = 100
dateList = []
for x in range (0, numdays):
    dateList.append(a - datetime.timedelta(days = x))
print dateList

回答 0

略胜一筹…

base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]

Marginally better…

base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]

回答 1

Pandas 一般而言,它非常适合时间序列,并且直接支持日期范围。

例如pd.date_range()

import pandas as pd
from datetime import datetime

datelist = pd.date_range(datetime.today(), periods=100).tolist()

它还具有许多使生活更轻松的选择。例如,如果您只想要工作日,则只需交换bdate_range

请参阅日期范围文档

此外,它完全支持pytz时区,并且可以平滑地跨越春季/秋季DST偏移。

OP编辑:

如果您需要实际的python日期时间,而不是Pandas时间戳:

import pandas as pd
from datetime import datetime

pd.date_range(end = datetime.today(), periods = 100).to_pydatetime().tolist()

#OR

pd.date_range(start="2018-09-09",end="2020-02-02")

这使用“ end”参数来匹配原始问题,但是如果您想降序使用日期:

pd.date_range(datetime.today(), periods=100).to_pydatetime().tolist()

Pandas is great for time series in general, and has direct support for date ranges.

For example pd.date_range():

import pandas as pd
from datetime import datetime

datelist = pd.date_range(datetime.today(), periods=100).tolist()

It also has lots of options to make life easier. For example if you only wanted weekdays, you would just swap in bdate_range.

See date range documentation

In addition it fully supports pytz timezones and can smoothly span spring/autumn DST shifts.

EDIT by OP:

If you need actual python datetimes, as opposed to Pandas timestamps:

import pandas as pd
from datetime import datetime

pd.date_range(end = datetime.today(), periods = 100).to_pydatetime().tolist()

#OR

pd.date_range(start="2018-09-09",end="2020-02-02")

This uses the “end” parameter to match the original question, but if you want descending dates:

pd.date_range(datetime.today(), periods=100).to_pydatetime().tolist()

回答 2

获取指定开始日期和结束日期之间的日期范围(针对时间和空间复杂度进行了优化):

import datetime

start = datetime.datetime.strptime("21-06-2014", "%d-%m-%Y")
end = datetime.datetime.strptime("07-07-2014", "%d-%m-%Y")
date_generated = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]

for date in date_generated:
    print date.strftime("%d-%m-%Y")

Get range of dates between specified start and end date (Optimized for time & space complexity):

import datetime

start = datetime.datetime.strptime("21-06-2014", "%d-%m-%Y")
end = datetime.datetime.strptime("07-07-2014", "%d-%m-%Y")
date_generated = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]

for date in date_generated:
    print date.strftime("%d-%m-%Y")

回答 3

您可以编写一个生成器函数来返回从今天开始的日期对象:

import datetime

def date_generator():
  from_date = datetime.datetime.today()
  while True:
    yield from_date
    from_date = from_date - datetime.timedelta(days=1)

该生成器返回从今天开始的日期,并且一次返回一天。这是开始前三个日期的方法:

>>> import itertools
>>> dates = itertools.islice(date_generator(), 3)
>>> list(dates)
[datetime.datetime(2009, 6, 14, 19, 12, 21, 703890), datetime.datetime(2009, 6, 13, 19, 12, 21, 703890), datetime.datetime(2009, 6, 12, 19, 12, 21, 703890)]

与循环或列表理解相比,此方法的优势在于您可以返回任意多次。

编辑

使用生成器表达式而不是函数的更紧凑的版本:

date_generator = (datetime.datetime.today() - datetime.timedelta(days=i) for i in itertools.count())

用法:

>>> dates = itertools.islice(date_generator, 3)
>>> list(dates)
[datetime.datetime(2009, 6, 15, 1, 32, 37, 286765), datetime.datetime(2009, 6, 14, 1, 32, 37, 286836), datetime.datetime(2009, 6, 13, 1, 32, 37, 286859)]

You can write a generator function that returns date objects starting from today:

import datetime

def date_generator():
  from_date = datetime.datetime.today()
  while True:
    yield from_date
    from_date = from_date - datetime.timedelta(days=1)

This generator returns dates starting from today and going backwards one day at a time. Here is how to take the first 3 dates:

>>> import itertools
>>> dates = itertools.islice(date_generator(), 3)
>>> list(dates)
[datetime.datetime(2009, 6, 14, 19, 12, 21, 703890), datetime.datetime(2009, 6, 13, 19, 12, 21, 703890), datetime.datetime(2009, 6, 12, 19, 12, 21, 703890)]

The advantage of this approach over a loop or list comprehension is that you can go back as many times as you want.

Edit

A more compact version using a generator expression instead of a function:

date_generator = (datetime.datetime.today() - datetime.timedelta(days=i) for i in itertools.count())

Usage:

>>> dates = itertools.islice(date_generator, 3)
>>> list(dates)
[datetime.datetime(2009, 6, 15, 1, 32, 37, 286765), datetime.datetime(2009, 6, 14, 1, 32, 37, 286836), datetime.datetime(2009, 6, 13, 1, 32, 37, 286859)]

回答 4

是的,重新发明轮子…。只要在论坛上搜索,您将获得类似以下内容:

from dateutil import rrule
from datetime import datetime

list(rrule.rrule(rrule.DAILY,count=100,dtstart=datetime.now()))

yeah, reinvent the wheel…. just search the forum and you’ll get something like this:

from dateutil import rrule
from datetime import datetime

list(rrule.rrule(rrule.DAILY,count=100,dtstart=datetime.now()))

回答 5

您还可以使用日序使之更简单:

def date_range(start_date, end_date):
    for ordinal in range(start_date.toordinal(), end_date.toordinal()):
        yield datetime.date.fromordinal(ordinal)

或按照注释中的建议,您可以创建如下列表:

date_range = [
    datetime.date.fromordinal(ordinal) 
    for ordinal in range(
        start_date.toordinal(),
        end_date.toordinal(),
    )
]

You can also use the day ordinal to make it simpler:

def date_range(start_date, end_date):
    for ordinal in range(start_date.toordinal(), end_date.toordinal()):
        yield datetime.date.fromordinal(ordinal)

Or as suggested in the comments you can create a list like this:

date_range = [
    datetime.date.fromordinal(ordinal) 
    for ordinal in range(
        start_date.toordinal(),
        end_date.toordinal(),
    )
]

回答 6

我希望从该问题的标题中找到类似的内容range(),这样我就可以指定两个日期并创建一个包含所有日期的列表。这样,如果事先不知道这两个日期之间的天数,则无需计算。

因此,由于存在偏离主题的风险,因此此一线工作即可:

import datetime
start_date = datetime.date(2011, 01, 01)
end_date   = datetime.date(2014, 01, 01)

dates_2011_2013 = [ start_date + datetime.timedelta(n) for n in range(int ((end_date - start_date).days))]

此答案的全部功劳!

From the title of this question I was expecting to find something like range(), that would let me specify two dates and create a list with all the dates in between. That way one does not need to calculate the number of days between those two dates, if one does not know it beforehand.

So with the risk of being slightly off-topic, this one-liner does the job:

import datetime
start_date = datetime.date(2011, 01, 01)
end_date   = datetime.date(2014, 01, 01)

dates_2011_2013 = [ start_date + datetime.timedelta(n) for n in range(int ((end_date - start_date).days))]

All credits to this answer!


回答 7

这里有一个稍微不同的答案美国洛特的回答,让两个日期之间的日期列表的建设关startend。在下面的示例中,从2017年初到今天。

start = datetime.datetime(2017,1,1)
end = datetime.datetime.today()
daterange = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]

Here’s a slightly different answer building off of S.Lott’s answer that gives a list of dates between two dates start and end. In the example below, from the start of 2017 to today.

start = datetime.datetime(2017,1,1)
end = datetime.datetime.today()
daterange = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]

回答 8

我知道一个较晚的答案,但是我只是遇到了同样的问题,并决定在这方面缺少Python的内部范围函数,因此我在我的util模块中覆盖了它。

from __builtin__ import range as _range
from datetime import datetime, timedelta

def range(*args):
    if len(args) != 3:
        return _range(*args)
    start, stop, step = args
    if start < stop:
        cmp = lambda a, b: a < b
        inc = lambda a: a + step
    else:
        cmp = lambda a, b: a > b
        inc = lambda a: a - step
    output = [start]
    while cmp(start, stop):
        start = inc(start)
        output.append(start)

    return output

print range(datetime(2011, 5, 1), datetime(2011, 10, 1), timedelta(days=30))

A bit of a late answer I know, but I just had the same problem and decided that Python’s internal range function was a bit lacking in this respect so I’ve overridden it in a util module of mine.

from __builtin__ import range as _range
from datetime import datetime, timedelta

def range(*args):
    if len(args) != 3:
        return _range(*args)
    start, stop, step = args
    if start < stop:
        cmp = lambda a, b: a < b
        inc = lambda a: a + step
    else:
        cmp = lambda a, b: a > b
        inc = lambda a: a - step
    output = [start]
    while cmp(start, stop):
        start = inc(start)
        output.append(start)

    return output

print range(datetime(2011, 5, 1), datetime(2011, 10, 1), timedelta(days=30))

回答 9

根据我为自己写的答案:

import datetime;
print [(datetime.date.today() - datetime.timedelta(days=x)).strftime('%Y-%m-%d') for x in range(-5, 0)]

输出:

['2017-12-11', '2017-12-10', '2017-12-09', '2017-12-08', '2017-12-07']

区别在于我得到的是’ date‘对象,而不是’ datetime.datetime‘一个对象。

Based on answers I wrote for myself this:

import datetime;
print [(datetime.date.today() - datetime.timedelta(days=x)).strftime('%Y-%m-%d') for x in range(-5, 0)]

Output:

['2017-12-11', '2017-12-10', '2017-12-09', '2017-12-08', '2017-12-07']

The difference is that I get the ‘date‘ object, not the ‘datetime.datetime‘ one.


回答 10

如果有两个日期,并且您需要范围,请尝试

from dateutil import rrule, parser
date1 = '1995-01-01'
date2 = '1995-02-28'
datesx = list(rrule.rrule(rrule.DAILY, dtstart=parser.parse(date1), until=parser.parse(date2)))

If there are two dates and you need the range try

from dateutil import rrule, parser
date1 = '1995-01-01'
date2 = '1995-02-28'
datesx = list(rrule.rrule(rrule.DAILY, dtstart=parser.parse(date1), until=parser.parse(date2)))

回答 11

这是我根据自己的代码创建的要点,这可能会有所帮助。(我知道这个问题太旧了,但是其他人可以使用它)

https://gist.github.com/2287345

(下同)

import datetime
from time import mktime

def convert_date_to_datetime(date_object):
    date_tuple = date_object.timetuple()
    date_timestamp = mktime(date_tuple)
    return datetime.datetime.fromtimestamp(date_timestamp)

def date_range(how_many=7):
    for x in range(0, how_many):
        some_date = datetime.datetime.today() - datetime.timedelta(days=x)
        some_datetime = convert_date_to_datetime(some_date.date())
        yield some_datetime

def pick_two_dates(how_many=7):
    a = b = convert_date_to_datetime(datetime.datetime.now().date())
    for each_date in date_range(how_many):
        b = a
        a = each_date
        if a == b:
            continue
        yield b, a

Here is gist I created, from my own code, this might help. (I know the question is too old, but others can use it)

https://gist.github.com/2287345

(same thing below)

import datetime
from time import mktime

def convert_date_to_datetime(date_object):
    date_tuple = date_object.timetuple()
    date_timestamp = mktime(date_tuple)
    return datetime.datetime.fromtimestamp(date_timestamp)

def date_range(how_many=7):
    for x in range(0, how_many):
        some_date = datetime.datetime.today() - datetime.timedelta(days=x)
        some_datetime = convert_date_to_datetime(some_date.date())
        yield some_datetime

def pick_two_dates(how_many=7):
    a = b = convert_date_to_datetime(datetime.datetime.now().date())
    for each_date in date_range(how_many):
        b = a
        a = each_date
        if a == b:
            continue
        yield b, a

回答 12

这是一个供bash脚本获取工作日列表的衬板,它是python3。可以轻松地对其进行修改,最后的int是您想要的过去天数。

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.today() - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int(sys.argv[1])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 10

这是提供开始(或更确切地说,结束)日期的一种变体

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d \") for x in range(0,int(sys.argv[2])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/30 10

这是任意开始日期和结束日期的变体。并不是说这不是非常有效,但是对于在bash脚本中放入for循环是有好处的:

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") + datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int((datetime.datetime.strptime(sys.argv[2], \"%Y/%m/%d\") - datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\")).days)) if (datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\") + datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/15 2015/12/30

Here’s a one liner for bash scripts to get a list of weekdays, this is python 3. Easily modified for whatever, the int at the end is the number of days in the past you want.

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.today() - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int(sys.argv[1])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 10

Here is a variant to provide a start (or rather, end) date

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d \") for x in range(0,int(sys.argv[2])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/30 10

Here is a variant for arbitrary start and end dates. not that this isn’t terribly efficient, but is good for putting in a for loop in a bash script:

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") + datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int((datetime.datetime.strptime(sys.argv[2], \"%Y/%m/%d\") - datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\")).days)) if (datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\") + datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/15 2015/12/30

回答 13

Matplotlib相关

from matplotlib.dates import drange
import datetime

base = datetime.date.today()
end  = base + datetime.timedelta(days=100)
delta = datetime.timedelta(days=1)
l = drange(base, end, delta)

Matplotlib related

from matplotlib.dates import drange
import datetime

base = datetime.date.today()
end  = base + datetime.timedelta(days=100)
delta = datetime.timedelta(days=1)
l = drange(base, end, delta)

回答 14

我知道已经回答了,但是出于历史目的,我会给出答案,因为我认为这很简单。

import numpy as np
import datetime as dt
listOfDates=[date for date in np.arange(firstDate,lastDate,dt.timedelta(days=x))]

当然,它不会像代码高尔夫那样赢得胜利,但是我认为它很优雅。

I know this has been answered, but I’ll put down my answer for historical purposes, and since I think it is straight forward.

import numpy as np
import datetime as dt
listOfDates=[date for date in np.arange(firstDate,lastDate,dt.timedelta(days=x))]

Sure it won’t win anything like code-golf, but I think it is elegant.


回答 15

从Sandeep的答案开始,另一个向前或向后计数的示例。

from datetime import date, datetime, timedelta
from typing import Sequence
def range_of_dates(start_of_range: date, end_of_range: date) -> Sequence[date]:

    if start_of_range <= end_of_range:
        return [
            start_of_range + timedelta(days=x)
            for x in range(0, (end_of_range - start_of_range).days + 1)
        ]
    return [
        start_of_range - timedelta(days=x)
        for x in range(0, (start_of_range - end_of_range).days + 1)
    ]

start_of_range = datetime.today().date()
end_of_range = start_of_range + timedelta(days=3)
date_range = range_of_dates(start_of_range, end_of_range)
print(date_range)

[datetime.date(2019, 12, 20), datetime.date(2019, 12, 21), datetime.date(2019, 12, 22), datetime.date(2019, 12, 23)]

start_of_range = datetime.today().date()
end_of_range = start_of_range - timedelta(days=3)
date_range = range_of_dates(start_of_range, end_of_range)
print(date_range)

[datetime.date(2019, 12, 20), datetime.date(2019, 12, 19), datetime.date(2019, 12, 18), datetime.date(2019, 12, 17)]

请注意,开始日期包含在退货中,因此,如果您要总共四个日期,请使用 timedelta(days=3)

Another example that counts forwards or backwards, starting from Sandeep’s answer.

from datetime import date, datetime, timedelta
from typing import Sequence
def range_of_dates(start_of_range: date, end_of_range: date) -> Sequence[date]:

    if start_of_range <= end_of_range:
        return [
            start_of_range + timedelta(days=x)
            for x in range(0, (end_of_range - start_of_range).days + 1)
        ]
    return [
        start_of_range - timedelta(days=x)
        for x in range(0, (start_of_range - end_of_range).days + 1)
    ]

start_of_range = datetime.today().date()
end_of_range = start_of_range + timedelta(days=3)
date_range = range_of_dates(start_of_range, end_of_range)
print(date_range)

gives

[datetime.date(2019, 12, 20), datetime.date(2019, 12, 21), datetime.date(2019, 12, 22), datetime.date(2019, 12, 23)]

and

start_of_range = datetime.today().date()
end_of_range = start_of_range - timedelta(days=3)
date_range = range_of_dates(start_of_range, end_of_range)
print(date_range)

gives

[datetime.date(2019, 12, 20), datetime.date(2019, 12, 19), datetime.date(2019, 12, 18), datetime.date(2019, 12, 17)]

Note that the start date is included in the return, so if you want four total dates, use timedelta(days=3)


回答 16

from datetime import datetime, timedelta
from dateutil import parser
def getDateRange(begin, end):
    """  """
    beginDate = parser.parse(begin)
    endDate =  parser.parse(end)
    delta = endDate-beginDate
    numdays = delta.days + 1
    dayList = [datetime.strftime(beginDate + timedelta(days=x), '%Y%m%d') for x in range(0, numdays)]
    return dayList
from datetime import datetime, timedelta
from dateutil import parser
def getDateRange(begin, end):
    """  """
    beginDate = parser.parse(begin)
    endDate =  parser.parse(end)
    delta = endDate-beginDate
    numdays = delta.days + 1
    dayList = [datetime.strftime(beginDate + timedelta(days=x), '%Y%m%d') for x in range(0, numdays)]
    return dayList

回答 17

具有datetime和的每月日期范围生成器dateutil。简单易懂:

import datetime as dt
from dateutil.relativedelta import relativedelta

def month_range(start_date, n_months):
        for m in range(n_months):
            yield start_date + relativedelta(months=+m)

A monthly date range generator with datetime and dateutil. Simple and easy to understand:

import datetime as dt
from dateutil.relativedelta import relativedelta

def month_range(start_date, n_months):
        for m in range(n_months):
            yield start_date + relativedelta(months=+m)

回答 18

import datetime    
def date_generator():
    cur = base = datetime.date.today()
    end  = base + datetime.timedelta(days=100)
    delta = datetime.timedelta(days=1)
    while(end>base):
        base = base+delta
        print base

date_generator()
import datetime    
def date_generator():
    cur = base = datetime.date.today()
    end  = base + datetime.timedelta(days=100)
    delta = datetime.timedelta(days=1)
    while(end>base):
        base = base+delta
        print base

date_generator()

回答 19

从以上答案中,我为日期生成器创建了此示例

import datetime
date = datetime.datetime.now()
time = date.time()
def date_generator(date, delta):
  counter =0
  date = date - datetime.timedelta(days=delta)
  while counter <= delta:
    yield date
    date = date + datetime.timedelta(days=1)
    counter +=1

for date in date_generator(date, 30):
   if date.date() != datetime.datetime.now().date():
     start_date = datetime.datetime.combine(date, datetime.time())
     end_date = datetime.datetime.combine(date, datetime.time.max)
   else:
     start_date = datetime.datetime.combine(date, datetime.time())
     end_date = datetime.datetime.combine(date, time)
   print('start_date---->',start_date,'end_date---->',end_date)

From above answers i created this example for date generator

import datetime
date = datetime.datetime.now()
time = date.time()
def date_generator(date, delta):
  counter =0
  date = date - datetime.timedelta(days=delta)
  while counter <= delta:
    yield date
    date = date + datetime.timedelta(days=1)
    counter +=1

for date in date_generator(date, 30):
   if date.date() != datetime.datetime.now().date():
     start_date = datetime.datetime.combine(date, datetime.time())
     end_date = datetime.datetime.combine(date, datetime.time.max)
   else:
     start_date = datetime.datetime.combine(date, datetime.time())
     end_date = datetime.datetime.combine(date, time)
   print('start_date---->',start_date,'end_date---->',end_date)

将值附加到Python中的集合

问题:将值附加到Python中的集合

我有这样的一套:

keep = set(generic_drugs_mapping[drug] for drug in drug_input)

如何将值添加[0,1,2,3,4,5,6,7,8,9,10]到此集中?

I have a set like this:

keep = set(generic_drugs_mapping[drug] for drug in drug_input)

How do I add values [0,1,2,3,4,5,6,7,8,9,10] into this set?


回答 0

keep.update(yoursequenceofvalues)

例如,keep.update(xrange(11))对于您的特定示例。或者,如果由于某些其他原因必须在循环中生成值,

for ...whatever...:
  onemorevalue = ...whatever...
  keep.add(onemorevalue)

但是,当然.update,在其他可行的情况下,只需一次调用即可批量执行此操作更快,更方便。

keep.update(yoursequenceofvalues)

e.g, keep.update(xrange(11)) for your specific example. Or, if you have to produce the values in a loop for some other reason,

for ...whatever...:
  onemorevalue = ...whatever...
  keep.add(onemorevalue)

But, of course, doing it in bulk with a single .update call is faster and handier, when otherwise feasible.


回答 1

定义集合

a = set()

使用添加附加单个值

a.add(1)
a.add(2)

使用update从元组,集合,列表或冻结集合中添加元素

a.update([3,4])

>> print(a)
{1, 2, 3, 4}

如果要添加元组或冻结集本身,请使用add

a.add((5, 6))

>> print(a)
{1, 2, 3, 4, (5, 6)}

注意:由于集合元素必须是可哈希的,并且列表被认为是可变的,因此不能将列表添加到集合中。您也不能将其他集合添加到集合中。但是,您可以从列表和集合中添加元素,如“ .update”方法所示。

Define set

a = set()

Use add to append single values

a.add(1)
a.add(2)

Use update to add elements from tuples, sets, lists or frozen-sets

a.update([3,4])

>> print(a)
{1, 2, 3, 4}

If you want to add a tuple or frozen-set itself, use add

a.add((5, 6))

>> print(a)
{1, 2, 3, 4, (5, 6)}

Note: Since set elements must be hashable, and lists are considered mutable, you cannot add a list to a set. You also cannot add other sets to a set. You can however, add the elements from lists and sets as demonstrated with the “.update” method.


回答 2

您还可以使用|运算符来连接两个集合(集合理论中的集):

>>> my_set = {1}
>>> my_set = my_set | {2}
>>> my_set
{1, 2}

或更短的形式使用|=

>>> my_set = {1}
>>> my_set |= {2}
>>> my_set
{1, 2}

注意:在Python 2.7之前的版本中,请使用set([...])代替{...}

You can also use the | operator to concatenate two sets (union in set theory):

>>> my_set = {1}
>>> my_set = my_set | {2}
>>> my_set
{1, 2}

Or a shorter form using |=:

>>> my_set = {1}
>>> my_set |= {2}
>>> my_set
{1, 2}

Note: In versions prior to Python 2.7, use set([...]) instead of {...}.


回答 3

update像这样使用:

keep.update(newvalues)

Use update like this:

keep.update(newvalues)

回答 4

这个问题是第一个在Google查询“ Python如何添加要设置的元素”时显示在Google上的问题,因此,值得注意的是,如果您想将整个字符串添加到集合中,则应添加.add(),不.update()

假设您有一个foo_str内容为的字符串'this is a sentence',并且有一些bar_set等于set()

如果这样做 bar_set.update(foo_str),您设置的内容将是{'t', 'a', ' ', 'e', 's', 'n', 'h', 'c', 'i'}

如果这样做bar_set.add(foo_str),您设置的内容将是{'this is a sentence'}

This question is the first one that shows up on Google when one looks up “Python how to add elements to set”, so it’s worth noting explicitly that, if you want to add a whole string to a set, it should be added with .add(), not .update().

Say you have a string foo_str whose contents are 'this is a sentence', and you have some set bar_set equal to set().

If you do bar_set.update(foo_str), the contents of your set will be {'t', 'a', ' ', 'e', 's', 'n', 'h', 'c', 'i'}.

If you do bar_set.add(foo_str), the contents of your set will be {'this is a sentence'}.


回答 5

我喜欢这样做的方法是将原始集合和想要添加的值都转换为列表,添加它们,然后将它们转换回集合,如下所示:

setMenu = {"Eggs", "Bacon"}
print(setMenu)
> {'Bacon', 'Eggs'}
setMenu = set(list(setMenu) + list({"Spam"}))
print(setMenu)
> {'Bacon', 'Spam', 'Eggs'}
setAdditions = {"Lobster", "Sausage"}
setMenu = set(list(setMenu) + list(setAdditions))
print(setMenu)
> {'Lobster', 'Spam', 'Eggs', 'Sausage', 'Bacon'}

这样,我也可以使用相同的逻辑轻松添加多个集合,TypeError: unhashable type: 'set'如果尝试使用该.update()方法,则会得到一个提示。

The way I like to do this is to convert both the original set and the values I’d like to add into lists, add them, and then convert them back into a set, like this:

setMenu = {"Eggs", "Bacon"}
print(setMenu)
> {'Bacon', 'Eggs'}
setMenu = set(list(setMenu) + list({"Spam"}))
print(setMenu)
> {'Bacon', 'Spam', 'Eggs'}
setAdditions = {"Lobster", "Sausage"}
setMenu = set(list(setMenu) + list(setAdditions))
print(setMenu)
> {'Lobster', 'Spam', 'Eggs', 'Sausage', 'Bacon'}

This way I can also easily add multiple sets using the same logic, which gets me an TypeError: unhashable type: 'set' if I try doing it with the .update() method.


回答 6

keep.update((0,1,2,3,4,5,6,7,8,9,10))

要么

keep.update(np.arange(11))
keep.update((0,1,2,3,4,5,6,7,8,9,10))

Or

keep.update(np.arange(11))

回答 7

对我来说,在Python 3中,它的工作方式很简单:

keep = keep.union((0,1,2,3,4,5,6,7,8,9,10))

我不知道这是否正确…

For me, in Python 3, it’s working simply in this way:

keep = keep.union((0,1,2,3,4,5,6,7,8,9,10))

I don’t know if it may be correct…


读取整个文件是否会使文件句柄保持打开状态?

问题:读取整个文件是否会使文件句柄保持打开状态?

如果您读取整个文件时content = open('Path/to/file', 'r').read(),文件句柄是否一直打开直到脚本退出?有没有更简洁的方法来读取整个文件?

If you read an entire file with content = open('Path/to/file', 'r').read() is the file handle left open until the script exits? Is there a more concise method to read a whole file?


回答 0

这个问题的答案在某种程度上取决于特定的Python实现。

要了解所有内容,请特别注意实际file对象。在您的代码中,该对象仅在表达式中被提及一次,并且在read()调用返回后立即变得不可访问。

这意味着文件对象是垃圾。剩下的唯一问题是“垃圾收集器何时收集文件对象?”。

在使用引用计数器的CPython中,这种垃圾立即被注意到,因此将立即被收集。这通常不适用于其他python实现。

确保该文件已关闭的一种更好的解决方案是以下模式:

with open('Path/to/file', 'r') as content_file:
    content = content_file.read()

块结束后,它将始终立即关闭文件;即使发生异常。

编辑:在上面提出一个更好的点:

除了file.__exit__(),这是在with上下文管理器设置中“自动”调用的,唯一file.close()可以自动调用的其他方法(即,除了自己明确调用之外)是via file.__del__()。这就引出了我们什么时候__del__()打电话的问题?

正确编写的程序不能假定终结器将在程序终止之前的任何时候运行。

https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203

特别是:

从不显式销毁对象。但是,当它们变得不可访问时,它们可能会被垃圾回收。允许实现推迟或完全取消垃圾回收 -只要没有收集仍可到达的对象,垃圾回收的实现方式就取决于实现质量。

[…]

CPython当前使用带有循环计数垃圾的(可选)延迟检测的引用计数方案,该方案会在无法访问时立即收集大多数对象,但不能保证收集包含循环引用的垃圾。

https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types

(强调我的)

但正如它暗示的那样,其他实现可能具有其他行为。例如,PyPy 6种不同的垃圾回收实现

The answer to that question depends somewhat on the particular Python implementation.

To understand what this is all about, pay particular attention to the actual file object. In your code, that object is mentioned only once, in an expression, and becomes inaccessible immediately after the read() call returns.

This means that the file object is garbage. The only remaining question is “When will the garbage collector collect the file object?”.

in CPython, which uses a reference counter, this kind of garbage is noticed immediately, and so it will be collected immediately. This is not generally true of other python implementations.

A better solution, to make sure that the file is closed, is this pattern:

with open('Path/to/file', 'r') as content_file:
    content = content_file.read()

which will always close the file immediately after the block ends; even if an exception occurs.

Edit: To put a finer point on it:

Other than file.__exit__(), which is “automatically” called in a with context manager setting, the only other way that file.close() is automatically called (that is, other than explicitly calling it yourself,) is via file.__del__(). This leads us to the question of when does __del__() get called?

A correctly-written program cannot assume that finalizers will ever run at any point prior to program termination.

https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203

In particular:

Objects are never explicitly destroyed; however, when they become unreachable they may be garbage-collected. An implementation is allowed to postpone garbage collection or omit it altogether — it is a matter of implementation quality how garbage collection is implemented, as long as no objects are collected that are still reachable.

[…]

CPython currently uses a reference-counting scheme with (optional) delayed detection of cyclically linked garbage, which collects most objects as soon as they become unreachable, but is not guaranteed to collect garbage containing circular references.

https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types

(Emphasis mine)

but as it suggests, other implementations may have other behavior. As an example, PyPy has 6 different garbage collection implementations!


回答 1

您可以使用pathlib

对于Python 3.5及更高版本:

from pathlib import Path
contents = Path(file_path).read_text()

对于旧版本的Python,请使用pathlib2

$ pip install pathlib2

然后:

from pathlib2 import Path
contents = Path(file_path).read_text()

这是实际的read_text 实现

def read_text(self, encoding=None, errors=None):
    """
    Open the file in text mode, read it, and close the file.
    """
    with self.open(mode='r', encoding=encoding, errors=errors) as f:
        return f.read()

You can use pathlib.

For Python 3.5 and above:

from pathlib import Path
contents = Path(file_path).read_text()

For older versions of Python use pathlib2:

$ pip install pathlib2

Then:

from pathlib2 import Path
contents = Path(file_path).read_text()

This is the actual read_text implementation:

def read_text(self, encoding=None, errors=None):
    """
    Open the file in text mode, read it, and close the file.
    """
    with self.open(mode='r', encoding=encoding, errors=errors) as f:
        return f.read()

回答 2

好吧,如果您必须逐行读取文件才能使用每一行,则可以使用

with open('Path/to/file', 'r') as f:
    s = f.readline()
    while s:
        # do whatever you want to
        s = f.readline()

甚至更好的方法:

with open('Path/to/file') as f:
    for line in f:
        # do whatever you want to

Well, if you have to read file line by line to work with each line, you can use

with open('Path/to/file', 'r') as f:
    s = f.readline()
    while s:
        # do whatever you want to
        s = f.readline()

Or even better way:

with open('Path/to/file') as f:
    for line in f:
        # do whatever you want to

回答 3

与其将文件内容作为单个字符串检索,不如将其存储为文件包括的所有行的列表,这很方便:

with open('Path/to/file', 'r') as content_file:
    content_list = content_file.read().strip().split("\n")

可以看出,一个需要经连结的方法添加.strip().split("\n")这个线程的主要答案

在这里,.strip()只需删除整个文件字符串末尾的空格和换行符,并.split("\n")通过在每个换行符 \ n处拆分整个文件字符串来生成实际列表。

而且,这种方式可以将整个文件内容存储在一个变量中,这在某些情况下可能是需要的,而不是像在文件中指出的那样逐行循环文件。 先前的答案中

Instead of retrieving the file content as a single string, it can be handy to store the content as a list of all lines the file comprises:

with open('Path/to/file', 'r') as content_file:
    content_list = content_file.read().strip().split("\n")

As can be seen, one needs to add the concatenated methods .strip().split("\n") to the main answer in this thread.

Here, .strip() just removes whitespace and newline characters at the endings of the entire file string, and .split("\n") produces the actual list via splitting the entire file string at every newline character \n.

Moreover, this way the entire file content can be stored in a variable, which might be desired in some cases, instead of looping over the file line by line as pointed out in this previous answer.