标签归档:Python

使用Python 3从Jupyter Notebook中相对导入的另一个目录中的模块导入本地函数

问题:使用Python 3从Jupyter Notebook中相对导入的另一个目录中的模块导入本地函数

我有一个类似于以下内容的目录结构

meta_project
    project1
        __init__.py
        lib
            module.py
            __init__.py
    notebook_folder
        notebook.jpynb

当在工作notebook.jpynb,如果我尝试使用相对导入来访问函数function()module.py有:

from ..project1.lib.module import function

我收到以下错误:

SystemError                               Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function

SystemError: Parent module '' not loaded, cannot perform relative import

有什么办法可以使用相对导入来使它起作用?

注意,笔记本服务器是在meta_project目录级别实例化的,因此它应该有权访问这些文件中的信息。

同样要注意的是,至少没有按照最初的意图project1被认为是模块,因此没有__init__.py文件,它只是作为文件系统目录。如果解决问题的方法需要将其视为模块,并包括一个__init__.py很好的文件(甚至是空白文件),但这样做还不足以解决问题。

我在机器之间共享此目录,相对的导入使我可以在任何地方使用相同的代码,而且我经常使用笔记本进行快速原型制作,因此涉及将绝对路径捆绑在一起的建议不太可能有帮助。


编辑:这与Python 3中的相对导入不同,后者相对于Python 3中的相对导入一般来说,尤其是从包目录中运行脚本。这与在jupyter笔记本中工作有关,该笔记本试图调用另一个目录中具有不同常规和特定方面的本地模块中的函数。

I have a directory structure similar to the following

meta_project
    project1
        __init__.py
        lib
            module.py
            __init__.py
    notebook_folder
        notebook.jpynb

When working in notebook.jpynb if I try to use a relative import to access a function function() in module.py with:

from ..project1.lib.module import function

I get the following error:

SystemError                               Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function

SystemError: Parent module '' not loaded, cannot perform relative import

Is there any way to get this to work using relative imports?

Note, the notebook server is instantiated at the level of the meta_project directory, so it should have access to the information in those files.

Note, also, that at least as originally intended project1 wasn’t thought of as a module and therefore does not have an __init__.py file, it was just meant as a file-system directory. If the solution to the problem requires treating it as a module and including an __init__.py file (even a blank one) that is fine, but doing so is not enough to solve the problem.

I share this directory between machines and relative imports allow me to use the same code everywhere, & I often use notebooks for quick prototyping, so suggestions that involve hacking together absolute paths are unlikely to be helpful.


Edit: This is unlike Relative imports in Python 3, which talks about relative imports in Python 3 in general and – in particular – running a script from within a package directory. This has to do with working within a jupyter notebook trying to call a function in a local module in another directory which has both different general and particular aspects.


回答 0

此笔记本中,我有一个与您几乎相同的示例,在我想以DRY方式说明相邻模块功能的用法。

我的解决方案是通过向笔记本中添加如下代码段来告知Python该额外的模块导入路径:

import os
import sys
module_path = os.path.abspath(os.path.join('..'))
if module_path not in sys.path:
    sys.path.append(module_path)

这使您可以从模块层次结构中导入所需的功能:

from project1.lib.module import function
# use the function normally
function(...)

请注意,如果还没有空__init__.py文件,则必须将它们添加到project1 /lib /文件夹中。

I had almost the same example as you in this notebook where I wanted to illustrate the usage of an adjacent module’s function in a DRY manner.

My solution was to tell Python of that additional module import path by adding a snippet like this one to the notebook:

import os
import sys
module_path = os.path.abspath(os.path.join('..'))
if module_path not in sys.path:
    sys.path.append(module_path)

This allows you to import the desired function from the module hierarchy:

from project1.lib.module import function
# use the function normally
function(...)

Note that it is necessary to add empty __init__.py files to project1/ and lib/ folders if you don’t have them already.


回答 1

在这里使用笔记本时,正在寻求将代码抽象到子模块的最佳实践。我不确定是否有最佳做法。我一直在提出这个建议。

这样的项目层次结构:

├── ipynb
   ├── 20170609-Examine_Database_Requirements.ipynb
   └── 20170609-Initial_Database_Connection.ipynb
└── lib
    ├── __init__.py
    └── postgres.py

来自20170609-Initial_Database_Connection.ipynb

    In [1]: cd ..

    In [2]: from lib.postgres import database_connection

之所以可行,是因为默认情况下Jupyter Notebook可以解析该cd命令。请注意,这没有利用Python Notebook魔术。它只是工作而无需前置%bash

考虑到我使用Project Jupyter Docker映像之一在Docker中工作的100次中有99次,以下修改幂等的

    In [1]: cd /home/jovyan

    In [2]: from lib.postgres import database_connection

Came here searching for best practices in abstracting code to submodules when working in Notebooks. I’m not sure that there is a best practice. I have been proposing this.

A project hierarchy as such:

├── ipynb
│   ├── 20170609-Examine_Database_Requirements.ipynb
│   └── 20170609-Initial_Database_Connection.ipynb
└── lib
    ├── __init__.py
    └── postgres.py

And from 20170609-Initial_Database_Connection.ipynb:

    In [1]: cd ..

    In [2]: from lib.postgres import database_connection

This works because by default the Jupyter Notebook can parse the cd command. Note that this does not make use of Python Notebook magic. It simply works without prepending %bash.

Considering that 99 times out of a 100 I am working in Docker using one of the Project Jupyter Docker images, the following modification is idempotent

    In [1]: cd /home/jovyan

    In [2]: from lib.postgres import database_connection

回答 2

到目前为止,已接受的答案对我来说效果最好。但是,我一直担心的是,在某些情况下,我可能会将notebooks目录重构为子目录,从而需要module_path在每个笔记本中进行更改。我决定在每个笔记本目录中添加一个python文件,以导入所需的模块。

因此,具有以下项目结构:

project
|__notebooks
   |__explore
      |__ notebook1.ipynb
      |__ notebook2.ipynb
      |__ project_path.py
   |__ explain
       |__notebook1.ipynb
       |__project_path.py
|__lib
   |__ __init__.py
   |__ module.py

project_path.py在每个笔记本子目录(notebooks/explorenotebooks/explain)中添加了文件。此文件包含相对导入的代码(来自@metakermit):

import sys
import os

module_path = os.path.abspath(os.path.join(os.pardir, os.pardir))
if module_path not in sys.path:
    sys.path.append(module_path)

这样,我只需要在project_path.py文件中而不是在笔记本中进行相对导入即可。然后,笔记本文件仅需要在导入project_path之前导入lib。例如在0.0-notebook.ipynb

import project_path
import lib

需要注意的是,逆转进口将行不通。这不起作用:

import lib
import project_path

因此在进口期间必须小心。

So far, the accepted answer has worked best for me. However, my concern has always been that there is a likely scenario where I might refactor the notebooks directory into subdirectories, requiring to change the module_path in every notebook. I decided to add a python file within each notebook directory to import the required modules.

Thus, having the following project structure:

project
|__notebooks
   |__explore
      |__ notebook1.ipynb
      |__ notebook2.ipynb
      |__ project_path.py
   |__ explain
       |__notebook1.ipynb
       |__project_path.py
|__lib
   |__ __init__.py
   |__ module.py

I added the file project_path.py in each notebook subdirectory (notebooks/explore and notebooks/explain). This file contains the code for relative imports (from @metakermit):

import sys
import os

module_path = os.path.abspath(os.path.join(os.pardir, os.pardir))
if module_path not in sys.path:
    sys.path.append(module_path)

This way, I just need to do relative imports within the project_path.py file, and not in the notebooks. The notebooks files would then just need to import project_path before importing lib. For example in 0.0-notebook.ipynb:

import project_path
import lib

The caveat here is that reversing the imports would not work. THIS DOES NOT WORK:

import lib
import project_path

Thus care must be taken during imports.


回答 3

我刚刚找到了这个漂亮的解决方案:

import sys; sys.path.insert(0, '..') # add parent folder path where lib folder is
import lib.store_load # store_load is a file on my library folder

您只需要该文件的某些功能

from lib.store_load import your_function_name

如果python版本> = 3.3,则不需要文件夹中的init.py文件

I have just found this pretty solution:

import sys; sys.path.insert(0, '..') # add parent folder path where lib folder is
import lib.store_load # store_load is a file on my library folder

You just want some functions of that file

from lib.store_load import your_function_name

If python version >= 3.3 you do not need init.py file in the folder


回答 4

我自己研究此主题并阅读答案,因此我建议使用path.py库,因为该提供了用于更改当前工作目录的上下文管理器。

然后你有类似的东西

import path
if path.Path('../lib').isdir():
    with path.Path('..'):
        import lib

虽然,您可能只是省略了isdir声明。

在这里,我将添加打印语句,以便于跟踪正在发生的事情

import path
import pandas

print(path.Path.getcwd())
print(path.Path('../lib').isdir())
if path.Path('../lib').isdir():
    with path.Path('..'):
        print(path.Path.getcwd())
        import lib
        print('Success!')
print(path.Path.getcwd())

在此示例中输出(其中lib在/home/jovyan/shared/notebooks/by-team/data-vis/demos/lib):

/home/jovyan/shared/notebooks/by-team/data-vis/demos/custom-chart
/home/jovyan/shared/notebooks/by-team/data-vis/demos
/home/jovyan/shared/notebooks/by-team/data-vis/demos/custom-chart

由于该解决方案使用上下文管理器,因此无论内核在单元之前处于什么状态,以及导入库代码引发了什么异常,都可以保证返回到先前的工作目录。

Researching this topic myself and having read the answers I recommend using the path.py library since it provides a context manager for changing the current working directory.

You then have something like

import path
if path.Path('../lib').isdir():
    with path.Path('..'):
        import lib

Although, you might just omit the isdir statement.

Here I’ll add print statements to make it easy to follow what’s happening

import path
import pandas

print(path.Path.getcwd())
print(path.Path('../lib').isdir())
if path.Path('../lib').isdir():
    with path.Path('..'):
        print(path.Path.getcwd())
        import lib
        print('Success!')
print(path.Path.getcwd())

which outputs in this example (where lib is at /home/jovyan/shared/notebooks/by-team/data-vis/demos/lib):

/home/jovyan/shared/notebooks/by-team/data-vis/demos/custom-chart
/home/jovyan/shared/notebooks/by-team/data-vis/demos
/home/jovyan/shared/notebooks/by-team/data-vis/demos/custom-chart

Since the solution uses a context manager, you are guaranteed to go back to your previous working directory, no matter what state your kernel was in before the cell and no matter what exceptions are thrown by importing your library code.


回答 5

这是我的2美分:

导入系统

映射模块文件所在的路径。就我而言,它是台式机

sys.path.append(’/ Users / John / Desktop’)

要么导入整个映射模块,要么然后使用.notation来映射诸如mapping.Shipping()的类。

导入映射#mapping.py是我的模块文件的名称

shipit = mapping.Shipment()#Shipment是我需要在映射模块中使用的类的名称

或从映射模块导入特定的类

从映射导入映射

shipit = Shipment()#现在,您不必使用.notation

Here’s my 2 cents:

import sys

map the path where the module file is located. In my case it was the desktop

sys.path.append(‘/Users/John/Desktop’)

Either import the whole mapping module BUT then you have to use the .notation to map the classes like mapping.Shipping()

import mapping #mapping.py is the name of my module file

shipit = mapping.Shipment() #Shipment is the name of the class I need to use in the mapping module

Or import the specific class from the mapping module

from mapping import Mapping

shipit = Shipment() #Now you don’t have to use the .notation


回答 6

我发现python-dotenv可以非常有效地解决此问题。您的项目结构最终会稍有变化,但是笔记本中的代码在笔记本之间更简单,更一致。

对于您的项目,请进行一些安装。

pipenv install python-dotenv

然后,项目更改为:

├── .env (this can be empty)
├── ipynb
   ├── 20170609-Examine_Database_Requirements.ipynb
   └── 20170609-Initial_Database_Connection.ipynb
└── lib
    ├── __init__.py
    └── postgres.py

最后,您的导入更改为:

import os
import sys

from dotenv import find_dotenv


sys.path.append(os.path.dirname(find_dotenv()))

此软件包的+1是您的笔记本可以位于多个目录中。python-dotenv将在父目录中找到最接近的目录并使用它。此方法的+2是jupyter将在启动时从.env文件加载环境变量。双重打击。

I have found that python-dotenv helps solve this issue pretty effectively. Your project structure ends up changing slightly, but the code in your notebook is a bit simpler and consistent across notebooks.

For your project, do a little install.

pipenv install python-dotenv

Then, project changes to:

├── .env (this can be empty)
├── ipynb
│   ├── 20170609-Examine_Database_Requirements.ipynb
│   └── 20170609-Initial_Database_Connection.ipynb
└── lib
    ├── __init__.py
    └── postgres.py

And finally, your import changes to:

import os
import sys

from dotenv import find_dotenv


sys.path.append(os.path.dirname(find_dotenv()))

A +1 for this package is that your notebooks can be several directories deep. python-dotenv will find the closest one in a parent directory and use it. A +2 for this approach is that jupyter will load environment variables from the .env file on startup. Double whammy.


Python-获取根项目结构的路径

问题:Python-获取根项目结构的路径

我在项目根目录中有一个带有配置文件的python项目。在整个项目中,需要使用几个不同的文件来访问配置文件。

所以它看起来是这样的:<ROOT>/configuration.conf <ROOT>/A/a.py<ROOT>/A/B/b.py(当b,a.py访问配置文件)。

在不依赖我所在项目中的哪个文件的情况下,获得项目根目录和配置文件路径的最佳/最简便方法是什么?即不使用../../?可以假设我们知道项目根目录的名称是可以的。

I’ve got a python project with a configuration file in the project root. The configuration file needs to be accessed in a few different files throughout the project.

So it looks something like: <ROOT>/configuration.conf <ROOT>/A/a.py, <ROOT>/A/B/b.py (when b,a.py access the configuration file).

What’s the best / easiest way to get the path to the project root and the configuration file without depending on which file inside the project I’m in? i.e without using ../../? It’s okay to assume that we know the project root’s name.


回答 0

您可以按照Django的方式进行操作:从项目顶层的文件中为项目根定义变量。例如,如果您的项目结构如下所示:

project/
    configuration.conf
    definitions.py
    main.py
    utils.py

在中definitions.py可以定义(这需要import os):

ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) # This is your Project Root

因此,在已知项目根目录的情况下,您可以创建一个指向配置位置的变量(可以在任何位置定义,但逻辑上的位置是将其放置在定义了常量的位置-例如definitions.py):

CONFIG_PATH = os.path.join(ROOT_DIR, 'configuration.conf')  # requires `import os`

然后,你可以很容易地访问与import语句(如中恒(在任何其他文件)utils.pyfrom definitions import CONFIG_PATH

You can do this how Django does it: define a variable to the Project Root from a file that is in the top-level of the project. For example, if this is what your project structure looks like:

project/
    configuration.conf
    definitions.py
    main.py
    utils.py

In definitions.py you can define (this requires import os):

ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) # This is your Project Root

Thus, with the Project Root known, you can create a variable that points to the location of the configuration (this can be defined anywhere, but a logical place would be to put it in a location where constants are defined – e.g. definitions.py):

CONFIG_PATH = os.path.join(ROOT_DIR, 'configuration.conf')  # requires `import os`

Then, you can easily access the constant (in any of the other files) with the import statement (e.g. in utils.py): from definitions import CONFIG_PATH.


回答 1

其他答案建议在项目的顶层使用文件。如果使用pathlib.Pathparent(Python 3.4及更高版本),则不需要这样做。考虑以下目录结构,其中除README.md和以外的所有文件utils.py均被省略。

project
   README.md
|
└───src
      utils.py
|   |   ...
|   ...

utils.py我们定义以下功能。

from pathlib import Path

def get_project_root() -> Path:
    return Path(__file__).parent.parent

现在,在项目的任何模块中,我们都可以按以下方式获取项目根目录。

from src.utils import get_project_root

root = get_project_root()

好处:调用的任何模块get_project_root都可以移动,而无需更改程序行为。只有在utils.py移动模块时,我们才需要更新get_project_root和导入(可以使用重构工具来自动执行此操作)。

Other answers advice to use a file in the top-level of the project. This is not necessary if you use pathlib.Path and parent (Python 3.4 and up). Consider the following directory structure where all files except README.md and utils.py have been omitted.

project
│   README.md
|
└───src
│   │   utils.py
|   |   ...
|   ...

In utils.py we define the following function.

from pathlib import Path

def get_project_root() -> Path:
    return Path(__file__).parent.parent

In any module in the project we can now get the project root as follows.

from src.utils import get_project_root

root = get_project_root()

Benefits: Any module which calls get_project_root can be moved without changing program behavior. Only when the module utils.py is moved we have to update get_project_root and the imports (refactoring tools can be used to automate this).


回答 2

对于我认为您需要的东西,以前的所有解决方案似乎都过于复杂,并且通常不适用于我。下面的单行命令可以满足您的要求:

import os
ROOT_DIR = os.path.abspath(os.curdir)

All the previous solutions seem to be overly complicated for what I think you need, and often didn’t work for me. The following one-line command does what you want:

import os
ROOT_DIR = os.path.abspath(os.curdir)

回答 3

要获取“ root”模块的路径,可以使用:

import os
import sys
os.path.dirname(sys.modules['__main__'].__file__)

但是更有趣的是,如果您在最顶层的模块中有一个配置“对象”,则可以像这样从中读取:

app = sys.modules['__main__']
stuff = app.config.somefunc()

To get the path of the “root” module, you can use:

import os
import sys
os.path.dirname(sys.modules['__main__'].__file__)

But more interestingly if you have an config “object” in your top-most module you could -read- from it like so:

app = sys.modules['__main__']
stuff = app.config.somefunc()

回答 4

实现此目的的标准方法是使用包装中的pkg_resources模块setuptoolssetuptools用于创建可安装的python软件包。

您可以使用pkg_resources以字符串形式返回所需文件的内容,并且可以使用pkg_resources用来获取系统上所需文件的实际路径。

假设您有一个名为的软件包stackoverflow

stackoverflow/
|-- app
|   `-- __init__.py
`-- resources
    |-- bands
    |   |-- Dream\ Theater
    |   |-- __init__.py
    |   |-- King's\ X
    |   |-- Megadeth
    |   `-- Rush
    `-- __init__.py

3 directories, 7 files

现在,假设您要从module访问文件Rush app.run。使用pkg_resources.resouces_filename得到的路径,拉什和pkg_resources.resource_string得到拉什的内容; 因此:

import pkg_resources

if __name__ == "__main__":
    print pkg_resources.resource_filename('resources.bands', 'Rush')
    print pkg_resources.resource_string('resources.bands', 'Rush')

输出:

/home/sri/workspace/stackoverflow/resources/bands/Rush
Base: Geddy Lee
Vocals: Geddy Lee
Guitar: Alex Lifeson
Drums: Neil Peart

这适用于您的python路径中的所有软件包。因此,如果您想知道lxml.etree系统上的位置:

import pkg_resources

if __name__ == "__main__":
    print pkg_resources.resource_filename('lxml', 'etree')

输出:

/usr/lib64/python2.7/site-packages/lxml/etree

关键是您可以使用此标准方法来访问系统上安装的文件(例如pip install xxx或yum -y install python-xxx)以及当前正在使用的模块中的文件。

A standard way to achieve this would be to use the pkg_resources module which is part of the setuptools package. setuptools is used to create an install-able python package.

You can use pkg_resources to return the contents of your desired file as a string and you can use pkg_resources to get the actual path of the desired file on your system.

Let’s say that you have a package called stackoverflow.

stackoverflow/
|-- app
|   `-- __init__.py
`-- resources
    |-- bands
    |   |-- Dream\ Theater
    |   |-- __init__.py
    |   |-- King's\ X
    |   |-- Megadeth
    |   `-- Rush
    `-- __init__.py

3 directories, 7 files

Now let’s say that you want to access the file Rush from a module app.run. Use pkg_resources.resouces_filename to get the path to Rush and pkg_resources.resource_string to get the contents of Rush; thusly:

import pkg_resources

if __name__ == "__main__":
    print pkg_resources.resource_filename('resources.bands', 'Rush')
    print pkg_resources.resource_string('resources.bands', 'Rush')

The output:

/home/sri/workspace/stackoverflow/resources/bands/Rush
Base: Geddy Lee
Vocals: Geddy Lee
Guitar: Alex Lifeson
Drums: Neil Peart

This works for all packages in your python path. So if you want to know where lxml.etree exists on your system:

import pkg_resources

if __name__ == "__main__":
    print pkg_resources.resource_filename('lxml', 'etree')

output:

/usr/lib64/python2.7/site-packages/lxml/etree

The point is that you can use this standard method to access files that are installed on your system (e.g pip install xxx or yum -y install python-xxx) and files that are within the module that you’re currently working on.


回答 5

尝试:

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Try:

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

回答 6

下面的代码返回直到您的项目根目录的路径

import sys
print(sys.path[1])

Below Code Returns the path until your project root

import sys
print(sys.path[1])

回答 7

在解决这个问题之前,我也一直在努力解决这个问题。我认为这是最干净的解决方案。

在您的setup.py中添加“程序包”

setup(
name='package_name'
version='0.0.1'
.
.
.
packages=['package_name']
.
.
.
)

在你的python_script.py中

import pkg_resources
import os

resource_package = pkg_resources.get_distribution(
    'package_name').location
config_path = os.path.join(resource_package,'configuration.conf')

I struggled with this problem too until I came to this solution. This is the cleanest solution in my opinion.

In your setup.py add “packages”

setup(
name='package_name'
version='0.0.1'
.
.
.
packages=['package_name']
.
.
.
)

In your python_script.py

import pkg_resources
import os

resource_package = pkg_resources.get_distribution(
    'package_name').location
config_path = os.path.join(resource_package,'configuration.conf')

回答 8

只是举个例子:我想运行runio.py从内部helper1.py

项目树示例:

myproject_root
- modules_dir/helpers_dir/helper1.py
- tools_dir/runio.py

获取项目根目录:

import os
rootdir = os.path.dirname(os.path.realpath(__file__)).rsplit(os.sep, 2)[0]

构建脚本的路径:

runme = os.path.join(rootdir, "tools_dir", "runio.py")
execfile(runme)

Just an example: I want to run runio.py from within helper1.py

Project tree example:

myproject_root
- modules_dir/helpers_dir/helper1.py
- tools_dir/runio.py

Get project root:

import os
rootdir = os.path.dirname(os.path.realpath(__file__)).rsplit(os.sep, 2)[0]

Build path to script:

runme = os.path.join(rootdir, "tools_dir", "runio.py")
execfile(runme)

回答 9

使用标准的PyCharm项目和虚拟环境(venv)在项目根目录下为我工作。

下面的代码并不是最漂亮的,但是始终能获得项目的根。它从VIRTUAL_ENV环境变量返回venv的完整目录路径,例如/Users/NAME/documents/PROJECT/venv

然后,它最后分割路径/,从而给出一个包含两个元素的数组。第一个元素将是项目路径,例如/Users/NAME/documents/PROJECT

import os

print(os.path.split(os.environ['VIRTUAL_ENV'])[0])

This worked for me using a standard PyCharm project with my virtual environment (venv) under the project root directory.

Code below isnt the prettiest, but consistently gets the project root. It returns the full directory path to venv from the VIRTUAL_ENV environment variable e.g. /Users/NAME/documents/PROJECT/venv

It then splits the path at the last /, giving an array with two elements. The first element will be the project path e.g. /Users/NAME/documents/PROJECT

import os

print(os.path.split(os.environ['VIRTUAL_ENV'])[0])

回答 10

我最近一直在尝试做类似的事情,但我发现这些答案不足以满足我的用例(需要检测项目根目录的分布式库)。主要是我一直在与不同的环境和平台作斗争,但仍然没有找到完全通用的东西。

项目本地代码

我已经看到了这个示例,并在一些地方(例如Django等)使用了该示例。

import os
print(os.path.dirname(os.path.abspath(__file__)))

如此简单,仅当代码片段所在的文件实际上是项目的一部分时才起作用。我们不检索项目目录,而是片段的目录

同样,从应用程序的入口点之外调用时,sys.modules方法会崩溃,特别是我观察到子线程无法在不与’ main ‘模块相关的情况下确定该方法。我已将导入明确地放在一个函数中,以演示从子线程进行的导入,将其移至app.py的顶层将对其进行修复。

app/
|-- config
|   `-- __init__.py
|   `-- settings.py
`-- app.py

app.py

#!/usr/bin/env python
import threading


def background_setup():
    # Explicitly importing this from the context of the child thread
    from config import settings
    print(settings.ROOT_DIR)


# Spawn a thread to background preparation tasks
t = threading.Thread(target=background_setup)
t.start()

# Do other things during initialization

t.join()

# Ready to take traffic

settings.py

import os
import sys


ROOT_DIR = None


def setup():
    global ROOT_DIR
    ROOT_DIR = os.path.dirname(sys.modules['__main__'].__file__)
    # Do something slow

运行此程序会产生属性错误:

>>> import main
>>> Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python2714\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Python2714\lib\threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "main.py", line 6, in background_setup
    from config import settings
  File "config\settings.py", line 34, in <module>
    ROOT_DIR = get_root()
  File "config\settings.py", line 31, in get_root
    return os.path.dirname(sys.modules['__main__'].__file__)
AttributeError: 'module' object has no attribute '__file__'

…因此基于线程的解决方案

位置无关

使用与以前相同的应用程序结构,但修改settings.py

import os
import sys
import inspect
import platform
import threading


ROOT_DIR = None


def setup():
    main_id = None
    for t in threading.enumerate():
        if t.name == 'MainThread':
            main_id = t.ident
            break

    if not main_id:
        raise RuntimeError("Main thread exited before execution")

    current_main_frame = sys._current_frames()[main_id]
    base_frame = inspect.getouterframes(current_main_frame)[-1]

    if platform.system() == 'Windows':
        filename = base_frame.filename
    else:
        filename = base_frame[0].f_code.co_filename

    global ROOT_DIR
    ROOT_DIR = os.path.dirname(os.path.abspath(filename))

分解如下:首先,我们要准确地找到主线程的线程ID。threading.main_thread()但是,在Python3.4 +中,线程库已经使用了,每个人都没有使用3.4+,因此我们在所有线程中进行搜索,以查找除ID外的主线程。如果主线程已经退出,则不会在中列出threading.enumerate()RuntimeError()在这种情况下,我们提出一个,直到找到更好的解决方案。

main_id = None
for t in threading.enumerate():
    if t.name == 'MainThread':
        main_id = t.ident
        break

if not main_id:
    raise RuntimeError("Main thread exited before execution")

接下来,我们找到主线程的第一个堆栈框架。使用特定于cPython的函数, sys._current_frames()我们可以获得每个线程当前堆栈框架的字典。然后利用inspect.getouterframes()我们可以检索主线程和第一帧的整个堆栈。current_main_frame = sys._current_frames()[main_id] base_frame = inspect.getouterframes(current_main_frame)[-1]最后,inspect.getouterframes()需要处理Windows和Linux实现之间的差异。使用清理后的文件名,os.path.abspath()然后进行os.path.dirname()清理。

if platform.system() == 'Windows':
    filename = base_frame.filename
else:
    filename = base_frame[0].f_code.co_filename

global ROOT_DIR
ROOT_DIR = os.path.dirname(os.path.abspath(filename))

到目前为止,我已经在Windows的Python2.7和3.6以及WSL的Python3.4上对此进行了测试

I’ve recently been trying to do something similar and I have found these answers inadequate for my use cases (a distributed library that needs to detect project root). Mainly I’ve been battling different environments and platforms, and still haven’t found something perfectly universal.

Code local to project

I’ve seen this example mentioned and used in a few places, Django, etc.

import os
print(os.path.dirname(os.path.abspath(__file__)))

Simple as this is, it only works when the file that the snippet is in is actually part of the project. We do not retrieve the project directory, but instead the snippet’s directory

Similarly, the sys.modules approach breaks down when called from outside the entrypoint of the application, specifically I’ve observed a child thread cannot determine this without relation back to the ‘main‘ module. I’ve explicitly put the import inside a function to demonstrate an import from a child thread, moving it to top level of app.py would fix it.

app/
|-- config
|   `-- __init__.py
|   `-- settings.py
`-- app.py

app.py

#!/usr/bin/env python
import threading


def background_setup():
    # Explicitly importing this from the context of the child thread
    from config import settings
    print(settings.ROOT_DIR)


# Spawn a thread to background preparation tasks
t = threading.Thread(target=background_setup)
t.start()

# Do other things during initialization

t.join()

# Ready to take traffic

settings.py

import os
import sys


ROOT_DIR = None


def setup():
    global ROOT_DIR
    ROOT_DIR = os.path.dirname(sys.modules['__main__'].__file__)
    # Do something slow

Running this program produces an attribute error:

>>> import main
>>> Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python2714\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\Python2714\lib\threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "main.py", line 6, in background_setup
    from config import settings
  File "config\settings.py", line 34, in <module>
    ROOT_DIR = get_root()
  File "config\settings.py", line 31, in get_root
    return os.path.dirname(sys.modules['__main__'].__file__)
AttributeError: 'module' object has no attribute '__file__'

…hence a threading-based solution

Location independent

Using the same application structure as before but modifying settings.py

import os
import sys
import inspect
import platform
import threading


ROOT_DIR = None


def setup():
    main_id = None
    for t in threading.enumerate():
        if t.name == 'MainThread':
            main_id = t.ident
            break

    if not main_id:
        raise RuntimeError("Main thread exited before execution")

    current_main_frame = sys._current_frames()[main_id]
    base_frame = inspect.getouterframes(current_main_frame)[-1]

    if platform.system() == 'Windows':
        filename = base_frame.filename
    else:
        filename = base_frame[0].f_code.co_filename

    global ROOT_DIR
    ROOT_DIR = os.path.dirname(os.path.abspath(filename))

Breaking this down: First we want to accurately find the thread ID of the main thread. In Python3.4+ the threading library has threading.main_thread() however, everybody doesn’t use 3.4+ so we search through all threads looking for the main thread save it’s ID. If the main thread has already exited, it won’t be listed in the threading.enumerate(). We raise a RuntimeError() in this case until I find a better solution.

main_id = None
for t in threading.enumerate():
    if t.name == 'MainThread':
        main_id = t.ident
        break

if not main_id:
    raise RuntimeError("Main thread exited before execution")

Next we find the very first stack frame of the main thread. Using the cPython specific function sys._current_frames() we get a dictionary of every thread’s current stack frame. Then utilizing inspect.getouterframes() we can retrieve the entire stack for the main thread and the very first frame. current_main_frame = sys._current_frames()[main_id] base_frame = inspect.getouterframes(current_main_frame)[-1] Finally, the differences between Windows and Linux implementations of inspect.getouterframes() need to be handled. Using the cleaned up filename, os.path.abspath() and os.path.dirname() clean things up.

if platform.system() == 'Windows':
    filename = base_frame.filename
else:
    filename = base_frame[0].f_code.co_filename

global ROOT_DIR
ROOT_DIR = os.path.dirname(os.path.abspath(filename))

So far I’ve tested this on Python2.7 and 3.6 on Windows as well as Python3.4 on WSL


回答 11

如果您正在使用anaconda-project,则可以从环境变量-> os.getenv(’PROJECT_ROOT’)查询PROJECT_ROOT。仅当脚本通过anaconda-project run执行时才有效。

如果您不希望脚本由anaconda-project运行,则可以查询正在使用的Python解释器的可执行二进制文件的绝对路径,并将路径字符串提取到envs目录exclusiv。例如:我的conda env的python解释器位于:

/ home / user / project_root / envs / default / bin / python

# You can first retrieve the env variable PROJECT_DIR.
# If not set, get the python interpreter location and strip off the string till envs inclusiv...

if os.getenv('PROJECT_DIR'):
    PROJECT_DIR = os.getenv('PROJECT_DIR')
else:
    PYTHON_PATH = sys.executable
    path_rem = os.path.join('envs', 'default', 'bin', 'python')
    PROJECT_DIR = py_path.split(path_rem)[0]

这仅适用于具有Python项目固定项目结构的conda项目

If you are working with anaconda-project, you can query the PROJECT_ROOT from the environment variable –> os.getenv(‘PROJECT_ROOT’). This works only if the script is executed via anaconda-project run .

If you do not want your script run by anaconda-project, you can query the absolute path of the executable binary of the Python interpreter you are using and extract the path string up to the envs directory exclusiv. For example: The python interpreter of my conda env is located at:

/home/user/project_root/envs/default/bin/python

# You can first retrieve the env variable PROJECT_DIR.
# If not set, get the python interpreter location and strip off the string till envs inclusiv...

if os.getenv('PROJECT_DIR'):
    PROJECT_DIR = os.getenv('PROJECT_DIR')
else:
    PYTHON_PATH = sys.executable
    path_rem = os.path.join('envs', 'default', 'bin', 'python')
    PROJECT_DIR = py_path.split(path_rem)[0]

This works only with conda-project with fixed project structure of a anaconda-project


回答 12

我使用../方法来获取当前项目路径。

例如:Project1-D:\ projects

src

配置文件

Configuration.cfg

路径=“ ../ src / ConfigurationFiles / Configuration.cfg”

I used the ../ method to fetch the current project path.

Example: Project1 — D:\projects

src

ConfigurationFiles

Configuration.cfg

Path=”../src/ConfigurationFiles/Configuration.cfg”


回答 13

在撰写本文时,没有其他解决方案是非常独立的。它们取决于环境变量或模块在包装结构中的位置。“ Django”解决方案的最高答案是后者的受害者,因为它需要相对导入。它还具有必须在顶层修改模块的缺点。

这应该是查找顶级软件包目录路径的正确方法:

import sys
import os

root_name, _, _ = __name__.partition('.')
root_module = sys.modules[root_name]
root_dir = os.path.dirname(root_module.__file__)

config_path = os.path.join(root_dir, 'configuration.conf')

它通过将其中包含的点分字符串中的第一个组件__name__用作键并将其用作sys.modules返回顶部包的模块对象的键来工作。其__file__属性包含/__init__.py使用修剪后我们想要的路径os.path.dirname()

该解决方案是独立的。它可以在包的任何模块中的任何位置运行,包括在顶级__init__.py文件中。

At the time of writing, none of the other solutions are very self-contained. They depend either on an environment variable or the position of the module in the package structure. The top answer with the ‘Django’ solution falls victim to the latter by requiring a relative import. It also has the disadvantage of having to modify a module at the top level.

This should be the correct approach for finding the directory path of the top-level package:

import sys
import os

root_name, _, _ = __name__.partition('.')
root_module = sys.modules[root_name]
root_dir = os.path.dirname(root_module.__file__)

config_path = os.path.join(root_dir, 'configuration.conf')

It works by taking the first component in the dotted string contained in __name__ and using it as a key in sys.modules which returns the module object of the top-level package. Its __file__ attribute contains the path we want after trimming off /__init__.py using os.path.dirname().

This solution is self-contained. It works anywhere in any module of the package, including in the top-level __init__.py file.


回答 14

我必须实现一个自定义解决方案,因为它没有您想象的那么简单。我的解决方案基于堆栈跟踪检查(inspect.stack())+ sys.path,无论在其中调用该函数的python模块的位置还是在解释器的位置都可以正常工作(我尝试通过在PyCharm中,在诗歌外壳等中运行它的方式来尝试… )。这是带有注释的完整实现:

def get_project_root_dir() -> str:
    """
    Returns the name of the project root directory.

    :return: Project root directory name
    """

    # stack trace history related to the call of this function
    frame_stack: [FrameInfo] = inspect.stack()

    # get info about the module that has invoked this function
    # (index=0 is always this very module, index=1 is fine as long this function is not called by some other
    # function in this module)
    frame_info: FrameInfo = frame_stack[1]

    # if there are multiple calls in the stacktrace of this very module, we have to skip those and take the first
    # one which comes from another module
    if frame_info.filename == __file__:
        for frame in frame_stack:
            if frame.filename != __file__:
                frame_info = frame
                break

    # path of the module that has invoked this function
    caller_path: str = frame_info.filename

    # absolute path of the of the module that has invoked this function
    caller_absolute_path: str = os.path.abspath(caller_path)

    # get the top most directory path which contains the invoker module
    paths: [str] = [p for p in sys.path if p in caller_absolute_path]
    paths.sort(key=lambda p: len(p))
    caller_root_path: str = paths[0]

    if not os.path.isabs(caller_path):
        # file name of the invoker module (eg: "mymodule.py")
        caller_module_name: str = Path(caller_path).name

        # this piece represents a subpath in the project directory
        # (eg. if the root folder is "myproject" and this function has ben called from myproject/foo/bar/mymodule.py
        # this will be "foo/bar")
        project_related_folders: str = caller_path.replace(os.sep + caller_module_name, '')

        # fix root path by removing the undesired subpath
        caller_root_path = caller_root_path.replace(project_related_folders, '')

    dir_name: str = Path(caller_root_path).name

    return dir_name

I had to implement a custom solution because it’s not as simple as you might think. My solution is based on stack trace inspection (inspect.stack()) + sys.path and is working fine no matter the location of the python module in which the function is invoked nor the interpreter (I tried by running it in PyCharm, in a poetry shell and other…). This is the full implementation with comments:

def get_project_root_dir() -> str:
    """
    Returns the name of the project root directory.

    :return: Project root directory name
    """

    # stack trace history related to the call of this function
    frame_stack: [FrameInfo] = inspect.stack()

    # get info about the module that has invoked this function
    # (index=0 is always this very module, index=1 is fine as long this function is not called by some other
    # function in this module)
    frame_info: FrameInfo = frame_stack[1]

    # if there are multiple calls in the stacktrace of this very module, we have to skip those and take the first
    # one which comes from another module
    if frame_info.filename == __file__:
        for frame in frame_stack:
            if frame.filename != __file__:
                frame_info = frame
                break

    # path of the module that has invoked this function
    caller_path: str = frame_info.filename

    # absolute path of the of the module that has invoked this function
    caller_absolute_path: str = os.path.abspath(caller_path)

    # get the top most directory path which contains the invoker module
    paths: [str] = [p for p in sys.path if p in caller_absolute_path]
    paths.sort(key=lambda p: len(p))
    caller_root_path: str = paths[0]

    if not os.path.isabs(caller_path):
        # file name of the invoker module (eg: "mymodule.py")
        caller_module_name: str = Path(caller_path).name

        # this piece represents a subpath in the project directory
        # (eg. if the root folder is "myproject" and this function has ben called from myproject/foo/bar/mymodule.py
        # this will be "foo/bar")
        project_related_folders: str = caller_path.replace(os.sep + caller_module_name, '')

        # fix root path by removing the undesired subpath
        caller_root_path = caller_root_path.replace(project_related_folders, '')

    dir_name: str = Path(caller_root_path).name

    return dir_name

回答 15

这里有很多答案,但我找不到涵盖所有情况的简单方法,因此也请提出我的解决方案:

import pathlib
import os

def get_project_root():
    """
    There is no way in python to get project root. This function uses a trick.
    We know that the function that is currently running is in the project.
    We know that the root project path is in the list of PYTHONPATH
    look for any path in PYTHONPATH list that is contained in this function's path
    Lastly we filter and take the shortest path because we are looking for the root.
    :return: path to project root
    """
    apth = str(pathlib.Path().absolute())
    ppth = os.environ['PYTHONPATH'].split(':')
    matches = [x for x in ppth if x in apth]
    project_root = min(matches, key=len)
    return project_root

There are many answers here but I couldn’t find something simple that covers all cases so allow me to suggest my solution too:

import pathlib
import os

def get_project_root():
    """
    There is no way in python to get project root. This function uses a trick.
    We know that the function that is currently running is in the project.
    We know that the root project path is in the list of PYTHONPATH
    look for any path in PYTHONPATH list that is contained in this function's path
    Lastly we filter and take the shortest path because we are looking for the root.
    :return: path to project root
    """
    apth = str(pathlib.Path().absolute())
    ppth = os.environ['PYTHONPATH'].split(':')
    matches = [x for x in ppth if x in apth]
    project_root = min(matches, key=len)
    return project_root

我可以将Python Windows软件包安装到virtualenvs吗?

问题:我可以将Python Windows软件包安装到virtualenvs吗?

Virtualenv很棒:它可以让我保留许多不同的Python安装,这样就不会将不同项目的依赖项放在一起。

但是,如果要在以.exe安装程序打包的Windows上安装软件包,如何将其定向安装到virtualenv中?例如,我有pycuda-0.94rc.win32-py2.6.exe。当我运行它时,它会检查注册表,并仅找到一个要安装到我的virtualenv所基于的通用Python26中。

如何引导它安装到virtualenv中?

Virtualenv is great: it lets me keep a number of distinct Python installations so that different projects’ dependencies aren’t all thrown together into a common pile.

But if I want to install a package on Windows that’s packaged as a .exe installer, how can I direct it to install into the virtualenv? For example, I have pycuda-0.94rc.win32-py2.6.exe. When I run it, it examines the registry, and finds only one Python26 to install into, the common one that my virtualenv is based off of.

How can I direct it to install into the virtualenv?


回答 0

是的你可以。所有你需要的是

easy_install binary_installer_built_with_distutils.exe

惊讶吗 看起来用distutils制作的Windows二进制安装程序将.exe和.zip合并为一个.exe文件。将扩展名更改为.zip以查看它是有效的zip文件。在阅读我的问题的答案后,我发现了这一点。在哪里可以从Windows下载带有psycopg2的二进制鸡蛋?

更新

正如Tritium21在他今天的回答中指出的那样,您应该使用pip代替easy_install。Pip无法安装distutils创建的二进制软件包,但可以在新版本中安装二进制软件包 wheel格式的。您可以使用滚轮套件将旧格式转换为新格式,必须先安装。

Yes, you can. All you need is

easy_install binary_installer_built_with_distutils.exe

Surprised? It looks like binary installers for Windows made with distutils combine .exe with .zip into one .exe file. Change extension to .zip to see it’s a valid zip file. I discovered this after reading answers to my question Where can I download binary eggs with psycopg2 for Windows?

UPDATE

As noted by Tritium21 in his answer nowadays you should use pip instead of easy_install. Pip can’t install binary packages created by distutils but it can install binary packages in the new wheel format. You can convert from old format to the new one using wheel package, which you have to install first.


回答 1

我知道这是一个很老的问题,并且早于我要谈论的工具,但是对于Google而言,我认为提这个问题是个好主意。easy_install是python包装的败类。没有人愿意承认使用这种新的流行点子。同样,尽管玩注册表技巧对于非标准EXE安装程序最为有效(有人自己安装了安装程序而不是使用distutils,并正在检查注册表中的安装路径),但现在有一种更好的方法用于标准EXE安装程序。

pip install wheel
wheel convert INSTALLER.EXE
pip install NEW_FILE_CREATED_IN_LAST_STEP.whl

在本博文中最近引入的轮式是蛋形的替代品,起着相同的作用。pip(virtualenv中已安装的工具)也支持此格式。

如果由于某种原因pip install WHEELFILE不起作用,请尝试wheel install WHEELFILE

I know this is quite an old question, and predates the tools I am about to talk about, but for the sake of Google, I think it is a good idea to mention it. easy_install is the black sheep of python packaging. No one wants to admit using it with the new hotness of pip around. Also, while playing registry tricks will work best for non-standard EXE installers (someone built the installer themselves instead of using distutils, and is checking the registry for the installation path), there is now a Better Way(c) for standard EXE installers.

pip install wheel
wheel convert INSTALLER.EXE
pip install NEW_FILE_CREATED_IN_LAST_STEP.whl

The wheel format, introduced recently as of this post, is the replacement for the egg format, filling much the same role. This format is also supported by pip (a tool already installed in your virtualenv).

if for some reason pip install WHEELFILE does not work, try wheel install WHEELFILE


回答 2

我最终修改了一个脚本(http://effbot.org/zone/python-register.htm)以在注册表中注册Python安装。我可以选择Python 作为注册表中 Python,运行Windows安装程序,然后重新设置注册表:

# -*- encoding: utf-8 -*-
#
# script to register Python 2.0 or later for use with win32all
# and other extensions that require Python registry settings
#
# Adapted by Ned Batchelder from a script
# written by Joakim Löw for Secret Labs AB / PythonWare
#
# source:
# http://www.pythonware.com/products/works/articles/regpy20.htm

import sys

from _winreg import *

# tweak as necessary
version = sys.version[:3]
installpath = sys.prefix

regpath = "SOFTWARE\\Python\\Pythoncore\\%s\\" % (version)
installkey = "InstallPath"
pythonkey = "PythonPath"
pythonpath = "%s;%s\\Lib\\;%s\\DLLs\\" % (
    installpath, installpath, installpath
)

def RegisterPy():
    try:
        reg = OpenKey(HKEY_LOCAL_MACHINE, regpath)
    except EnvironmentError:
        try:
            reg = CreateKey(HKEY_LOCAL_MACHINE, regpath)
        except Exception, e:
            print "*** Unable to register: %s" % e
            return

    SetValue(reg, installkey, REG_SZ, installpath)
    SetValue(reg, pythonkey, REG_SZ, pythonpath)
    CloseKey(reg)
    print "--- Python %s at %s is now registered!" % (version, installpath)

if __name__ == "__main__":
    RegisterPy()

使用您要注册的Python运行此脚本,它将被输入到注册表中。请注意,在Windows 7和Vista上,您需要具有管理员权限。

I ended up adapting a script (http://effbot.org/zone/python-register.htm) to register a Python installation in the registry. I can pick the Python to be the Python in the registry, run the Windows installer, then set the registry back:

# -*- encoding: utf-8 -*-
#
# script to register Python 2.0 or later for use with win32all
# and other extensions that require Python registry settings
#
# Adapted by Ned Batchelder from a script
# written by Joakim Löw for Secret Labs AB / PythonWare
#
# source:
# http://www.pythonware.com/products/works/articles/regpy20.htm

import sys

from _winreg import *

# tweak as necessary
version = sys.version[:3]
installpath = sys.prefix

regpath = "SOFTWARE\\Python\\Pythoncore\\%s\\" % (version)
installkey = "InstallPath"
pythonkey = "PythonPath"
pythonpath = "%s;%s\\Lib\\;%s\\DLLs\\" % (
    installpath, installpath, installpath
)

def RegisterPy():
    try:
        reg = OpenKey(HKEY_LOCAL_MACHINE, regpath)
    except EnvironmentError:
        try:
            reg = CreateKey(HKEY_LOCAL_MACHINE, regpath)
        except Exception, e:
            print "*** Unable to register: %s" % e
            return

    SetValue(reg, installkey, REG_SZ, installpath)
    SetValue(reg, pythonkey, REG_SZ, pythonpath)
    CloseKey(reg)
    print "--- Python %s at %s is now registered!" % (version, installpath)

if __name__ == "__main__":
    RegisterPy()

Run this script with the Python you want to be registered, and it will be entered into the registry. Note that on Windows 7 and Vista, you’ll need Administrator privileges.


回答 3

easy_install能够安装.exe软件包,只要它们是使用distutils的bdist_wininst目标构建的,该目标涵盖了许多流行的软件包。但是,还有许多其他方面不是(wxPython是我一直在努力的一种)

easy_install is able to install .exe packages as long as they were built using distutils’ bdist_wininst target, which covers many popular packages. However, there are many others that aren’t (wxPython is one that I’ve struggled with)


回答 4

您可以使用环境的easy_install来安装PyCUDA。

dev-env-path/bin/easy_install pycuda

它将为您提供相同的0.94rc版本。

在Windows上,easy_install.exe将位于Scripts目录中。

You can use environment’s easy_install to install PyCUDA.

dev-env-path/bin/easy_install pycuda

it will give you the same version 0.94rc.

On Windows easy_install.exe will be in Scripts directory.


回答 5

如果是.msi,则可以使用来指定命令行选项msiexec。Python 安装程序本身允许TARGETDIR,但是我不确定distutils是否将此安装到发行版安装程序中。

如果您使用.exe,我认为没有一种干净的方法。一种选择是使用诸如7Zip(或winzip等)之类的程序直接提取exe的内容,然后将relevent文件夹复制到您的虚拟site-packages文件夹中。例如,如果我解压缩“ processing-0.5.2.win32-py2.5.exe”,则会找到一个文件夹“ PLATLIB \ processing”,将其复制到virtualenv路径并可以使用,而不会出现任何运行时问题。(我不确定这是否总是那么简单。)

If it’s a .msi, you might be able to specify command line options using msiexec. The Python installer itself allows TARGETDIR, but I’m not sure if distutils bakes this into distribution installers.

If you’re using a .exe, I don’t think there’s a clean way. One option is to use a program like 7Zip (or winzip, etc) to directly extract the contents of the exe, then copy the relevent folders into your virtual site-packages folder. For example, if I extract “processing-0.5.2.win32-py2.5.exe”, I find a folder “PLATLIB\processing” which I copy to a virtualenv path and use without any runtime problems. (I’m not sure it’s always that simple though.)


Python使用枚举内部列表理解

问题:Python使用枚举内部列表理解

假设我有一个这样的列表:

mylist = ["a","b","c","d"]

要获得打印的值及其索引,我可以使用Python的enumerate函数,如下所示

>>> for i,j in enumerate(mylist):
...     print i,j
...
0 a
1 b
2 c
3 d
>>>

现在,当我尝试在A中使用它时,出现list comprehension了这个错误

>>> [i,j for i,j in enumerate(mylist)]
  File "<stdin>", line 1
    [i,j for i,j in enumerate(mylist)]
           ^
SyntaxError: invalid syntax

所以,我的问题是:在列表理解中使用枚举的正确方法是什么?

Lets suppose I have a list like this:

mylist = ["a","b","c","d"]

To get the values printed along with their index I can use Python’s enumerate function like this

>>> for i,j in enumerate(mylist):
...     print i,j
...
0 a
1 b
2 c
3 d
>>>

Now, when I try to use it inside a list comprehension it gives me this error

>>> [i,j for i,j in enumerate(mylist)]
  File "<stdin>", line 1
    [i,j for i,j in enumerate(mylist)]
           ^
SyntaxError: invalid syntax

So, my question is: what is the correct way of using enumerate inside list comprehension?


回答 0

试试这个:

[(i, j) for i, j in enumerate(mylist)]

您需要放入i,j一个元组以使列表理解起作用。另外,鉴于enumerate() 已经返回一个元组,您可以直接将其返回而无需先拆包:

[pair for pair in enumerate(mylist)]

无论哪种方式,返回的结果都是预期的:

> [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Try this:

[(i, j) for i, j in enumerate(mylist)]

You need to put i,j inside a tuple for the list comprehension to work. Alternatively, given that enumerate() already returns a tuple, you can return it directly without unpacking it first:

[pair for pair in enumerate(mylist)]

Either way, the result that gets returned is as expected:

> [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

回答 1

只需明确一点,这enumerate与列表理解语法无关。

此列表推导返回一个元组列表:

[(i,j) for i in range(3) for j in 'abc']

这是字典列表:

[{i:j} for i in range(3) for j in 'abc']

列表清单:

[[i,j] for i in range(3) for j in 'abc']

语法错误:

[i,j for i in range(3) for j in 'abc']

这是不一致的(IMHO),并且与字典理解语法混淆:

>>> {i:j for i,j in enumerate('abcdef')}
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}

和一组元组:

>>> {(i,j) for i,j in enumerate('abcdef')}
set([(0, 'a'), (4, 'e'), (1, 'b'), (2, 'c'), (5, 'f'), (3, 'd')])

正如ÓscarLópez所述,您可以直接通过枚举元组:

>>> [t for t in enumerate('abcdef') ] 
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f')]

Just to be really clear, this has nothing to do with enumerate and everything to do with list comprehension syntax.

This list comprehension returns a list of tuples:

[(i,j) for i in range(3) for j in 'abc']

this a list of dicts:

[{i:j} for i in range(3) for j in 'abc']

a list of lists:

[[i,j] for i in range(3) for j in 'abc']

a syntax error:

[i,j for i in range(3) for j in 'abc']

Which is inconsistent (IMHO) and confusing with dictionary comprehensions syntax:

>>> {i:j for i,j in enumerate('abcdef')}
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}

And a set of tuples:

>>> {(i,j) for i,j in enumerate('abcdef')}
set([(0, 'a'), (4, 'e'), (1, 'b'), (2, 'c'), (5, 'f'), (3, 'd')])

As Óscar López stated, you can just pass the enumerate tuple directly:

>>> [t for t in enumerate('abcdef') ] 
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f')]

回答 2

或者,如果您不坚持使用列表理解:

>>> mylist = ["a","b","c","d"]
>>> list(enumerate(mylist))
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Or, if you don’t insist on using a list comprehension:

>>> mylist = ["a","b","c","d"]
>>> list(enumerate(mylist))
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

回答 3

如果您使用的是长列表,则列表理解似乎会更快,更不用说可读性了。

~$ python -mtimeit -s"mylist = ['a','b','c','d']" "list(enumerate(mylist))"
1000000 loops, best of 3: 1.61 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[(i, j) for i, j in enumerate(mylist)]"
1000000 loops, best of 3: 0.978 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[t for t in enumerate(mylist)]"
1000000 loops, best of 3: 0.767 usec per loop

If you’re using long lists, it appears the list comprehension’s faster, not to mention more readable.

~$ python -mtimeit -s"mylist = ['a','b','c','d']" "list(enumerate(mylist))"
1000000 loops, best of 3: 1.61 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[(i, j) for i, j in enumerate(mylist)]"
1000000 loops, best of 3: 0.978 usec per loop
~$ python -mtimeit -s"mylist = ['a','b','c','d']" "[t for t in enumerate(mylist)]"
1000000 loops, best of 3: 0.767 usec per loop

回答 4

这是一种实现方法:

>>> mylist = ['a', 'b', 'c', 'd']
>>> [item for item in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

或者,您可以执行以下操作:

>>> [(i, j) for i, j in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

出现错误的原因是您错过了()ij使其成为一个元组。

Here’s a way to do it:

>>> mylist = ['a', 'b', 'c', 'd']
>>> [item for item in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Alternatively, you can do:

>>> [(i, j) for i, j in enumerate(mylist)]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

The reason you got an error was that you were missing the () around i and j to make it a tuple.


回答 5

明确说明元组。

[(i, j) for (i, j) in enumerate(mylist)]

Be explicit about the tuples.

[(i, j) for (i, j) in enumerate(mylist)]

回答 6

所有人都很好回答。我知道这里的问题是枚举所特有的,但是这样的话,又是另一个角度

from itertools import izip, count
a = ["5", "6", "1", "2"]
tupleList = list( izip( count(), a ) )
print(tupleList)

如果必须在性能方面并行迭代多个列表,它将变得更加强大。只是一个想法

a = ["5", "6", "1", "2"]
b = ["a", "b", "c", "d"]
tupleList = list( izip( count(), a, b ) )
print(tupleList)

All great answer guys. I know the question here is specific to enumeration but how about something like this, just another perspective

from itertools import izip, count
a = ["5", "6", "1", "2"]
tupleList = list( izip( count(), a ) )
print(tupleList)

It becomes more powerful, if one has to iterate multiple lists in parallel in terms of performance. Just a thought

a = ["5", "6", "1", "2"]
b = ["a", "b", "c", "d"]
tupleList = list( izip( count(), a, b ) )
print(tupleList)

在Mac上安装python模块的最兼容方法是什么?

问题:在Mac上安装python模块的最兼容方法是什么?

我开始学习python并热爱它。我主要在Mac和Linux上工作。我发现在Linux(主要是Ubuntu 9.04)上,使用apt-get安装python模块时,它工作正常。我可以轻松导入它。

在Mac上,我习惯于使用Macports安装所有Unixy东西。但是,我发现我安装的大多数python模块都没有被python看到。我花了一些时间玩弄PATH设置并使用python_select。什么都没有真正起作用,在这一点上我还不是很了解,相反,我只是闲逛。

我得到的印象是Macports在管理python模块方面并不广受喜爱。我想使用更“接受”(如果正确的话)的方法重新开始。

因此,我想知道Mac python开发人员使用什么方法来管理其模块?

奖励问题:

您使用Apple的python还是其他版本?您是从源代码编译所有内容,还是有运行良好的软件包管理器(Fink?)。

I’m starting to learn python and loving it. I work on a Mac mainly as well as Linux. I’m finding that on Linux (Ubuntu 9.04 mostly) when I install a python module using apt-get it works fine. I can import it with no trouble.

On the Mac, I’m used to using Macports to install all the Unixy stuff. However, I’m finding that most of the python modules I install with it are not being seen by python. I’ve spent some time playing around with PATH settings and using python_select . Nothing has really worked and at this point I’m not really understanding, instead I’m just poking around.

I get the impression that Macports isn’t universally loved for managing python modules. I’d like to start fresh using a more “accepted” (if that’s the right word) approach.

So, I was wondering, what is the method that Mac python developers use to manage their modules?

Bonus questions:

Do you use Apple’s python, or some other version? Do you compile everything from source or is there a package manger that works well (Fink?).


回答 0

管理python软件包的最流行方法(如果您不使用系统软件包管理器)是使用setuptools和easy_install。它可能已经安装在您的系统上。像这样使用它:

easy_install django

easy_install使用Python软件包索引 ,这对于python开发人员来说是一个了不起的资源。环顾四周,看看有哪些软件包可用。

更好的选择是pip,它越来越受欢迎,因为它试图解决与easy_install相关的许多问题。Pip使用与easy_install相同的软件包存储库,但效果更好。真正唯一需要使用easy_install的时间是此命令:

easy_install pip

之后,使用:

pip install django

在某个时候,您可能需要学习有关virtualenv的知识。如果您在软件包需求冲突的项目上进行大量的python开发,那么virtualenv是天赐之物。它将允许您使用各种软件包的完全不同的版本,并根据需要在它们之间轻松切换。

关于使用哪个python,坚持使用Apple的python会让您头疼最少,但是如果您需要更新的版本(我相信Leopard是2.5.1),我会选择macports python 2.6。

The most popular way to manage python packages (if you’re not using your system package manager) is to use setuptools and easy_install. It is probably already installed on your system. Use it like this:

easy_install django

easy_install uses the Python Package Index which is an amazing resource for python developers. Have a look around to see what packages are available.

A better option is pip, which is gaining traction, as it attempts to fix a lot of the problems associated with easy_install. Pip uses the same package repository as easy_install, it just works better. Really the only time use need to use easy_install is for this command:

easy_install pip

After that, use:

pip install django

At some point you will probably want to learn a bit about virtualenv. If you do a lot of python development on projects with conflicting package requirements, virtualenv is a godsend. It will allow you to have completely different versions of various packages, and switch between them easily depending your needs.

Regarding which python to use, sticking with Apple’s python will give you the least headaches, but If you need a newer version (Leopard is 2.5.1 I believe), I would go with the macports python 2.6.


回答 1

您的问题已经三岁了,有些其他答案未涵盖的细节:

我认识的大多数人都使用HomeBrewMacPorts,因此我更喜欢MacPorts,因为它清晰地默认了Mac OS X环境和我的开发设置。只需移出/ opt文件夹并使用普通用户Python环境测试您的软件包即可

MacPorts仅可在Mac中移植,但是通过easy_install或pip,您将学习如何在任何平台(Win / Mac / Linux / Bsd …)上设置环境。此外,它将始终是最新的,并且具有更多的软件包

我个人让MacPorts处理我的Python模块以保持所有更新。像任何其他高级软件包管理器(即apt-get)一样,对于具有大量二进制相关性的繁重模块而言,这要好得多。我无法用easy_install或pip构建Qt绑定(PySide)。Qt非常庞大,需要大量编译。一旦您想要一个需要非Python程序使用的库的Python包,请尝试避免easy_install或pip

在某些时候,您会发现MacPorts中缺少某些软件包。我不相信MacPorts会为您提供整个CheeseShop。例如,最近我需要Elixir模块,但是MacPorts仅提供py25-elixir和py26-elixir,没有py27版本。在这种情况下,您可以:

pip-2.7安装–user elixir

(确保您总是输入pip-(version))

这将在您的主目录中构建一个额外的Python库。是的,Python将在一个以上的库位置中工作:一个库由MacPorts控制,而一个用户本地库则用于MacPorts中缺少的所有内容。

现在注意,我更喜欢pip而不是easy_install。有充分的理由应该避免使用setuptools和easy_install。这是一个很好的解释,我尝试远离它们。pip的一项非常有用的功能是为您提供与MacPorts,easy_install和pip本身一起安装的所有模块(及其版本)的列表:

pip-2.7冻结

如果您已经开始使用easy_install,请放心,pip可以识别easy_install已经完成的所有操作,甚至可以升级随其安装的软件包。

如果您是开发人员,请密切注意virtualenv,以控制不同的设置和模块版本的组合。其他答案已经提到了它,到目前为止没有提到的是Tox模块,该工具用于测试您的软件包是否可以在不同的Python版本中正确安装。

尽管我通常没有版本冲突,但我还是喜欢virtualenv来设置一个干净的环境并清晰地查看我的软件包依赖项。这样,我就永远不会忘记setup.py中的任何依赖项

如果您选择MacPorts,请注意,不再选择同一软件包的多个版本,例如带有额外python_select软件包的旧Debian风格(出于兼容性,它仍然存在)。现在,您可以使用select命令选择将使用哪个Python版本(甚至可以选择Apple安装的版本):

$  port select python
Available versions for python:
    none
    python25-apple
    python26-apple
    python27 (active)
    python27-apple
    python32

$ port select python python32

在它上面添加tox,您的程序应该真正可移植

Your question is already three years old and there are some details not covered in other answers:

Most people I know use HomeBrew or MacPorts, I prefer MacPorts because of its clean cut of what is a default Mac OS X environment and my development setup. Just move out your /opt folder and test your packages with a normal user Python environment

MacPorts is only portable within Mac, but with easy_install or pip you will learn how to setup your environment in any platform (Win/Mac/Linux/Bsd…). Furthermore it will always be more up to date and with more packages

I personally let MacPorts handle my Python modules to keep everything updated. Like any other high level package manager (ie: apt-get) it is much better for the heavy lifting of modules with lots of binary dependencies. There is no way I would build my Qt bindings (PySide) with easy_install or pip. Qt is huge and takes a lot to compile. As soon as you want a Python package that needs a library used by non Python programs, try to avoid easy_install or pip

At some point you will find that there are some packages missing within MacPorts. I do not believe that MacPorts will ever give you the whole CheeseShop. For example, recently I needed the Elixir module, but MacPorts only offers py25-elixir and py26-elixir, no py27 version. In cases like these you have:

pip-2.7 install –user elixir

( make sure you always type pip-(version) )

That will build an extra Python library in your home dir. Yes, Python will work with more than one library location: one controlled by MacPorts and a user local one for everything missing within MacPorts.

Now notice that I favor pip over easy_install. There is a good reason you should avoid setuptools and easy_install. Here is a good explanation and I try to keep away from them. One very useful feature of pip is giving you a list of all the modules (along their versions) that you installed with MacPorts, easy_install and pip itself:

pip-2.7 freeze

If you already started using easy_install, don’t worry, pip can recognize everything done already by easy_install and even upgrade the packages installed with it.

If you are a developer keep an eye on virtualenv for controlling different setups and combinations of module versions. Other answers mention it already, what is not mentioned so far is the Tox module, a tool for testing that your package installs correctly with different Python versions.

Although I usually do not have version conflicts, I like to have virtualenv to set up a clean environment and get a clear view of my packages dependencies. That way I never forget any dependencies in my setup.py

If you go for MacPorts be aware that multiple versions of the same package are not selected anymore like the old Debian style with an extra python_select package (it is still there for compatibility). Now you have the select command to choose which Python version will be used (you can even select the Apple installed ones):

$  port select python
Available versions for python:
    none
    python25-apple
    python26-apple
    python27 (active)
    python27-apple
    python32

$ port select python python32

Add tox on top of it and your programs should be really portable


回答 2

请参阅Python OS X开发环境。最好的方法是使用MacPorts。下载并安装MacPorts,然后通过在终端中键入以下命令来通过MacPorts安装Python:

须藤端口安装python26 python_select
sudo端口选择--set python python26

要么

须藤端口安装python30 python_select
sudo端口选择--set python python30

使用第一组命令安装Python 2.6,使用第二组命令安装Python 3.0。然后使用:

sudo端口安装py26-packagename

要么

sudo端口安装py30-packagename

在上述命令中,将packagename替换为软件包的名称,例如:

sudo端口安装py26-setuptools

这些命令将自动为给定的Python版本安装软件包(及其依赖项)。

有关Python可用软件包的完整列表,请键入:

端口列表| grep py26-

要么

端口列表| grep py30-

您使用哪个命令取决于您选择安装的Python版本。

Please see Python OS X development environment. The best way is to use MacPorts. Download and install MacPorts, then install Python via MacPorts by typing the following commands in the Terminal:

sudo port install python26 python_select
sudo port select --set python python26

OR

sudo port install python30 python_select
sudo port select --set python python30

Use the first set of commands to install Python 2.6 and the second set to install Python 3.0. Then use:

sudo port install py26-packagename

OR

sudo port install py30-packagename

In the above commands, replace packagename with the name of the package, for example:

sudo port install py26-setuptools

These commands will automatically install the package (and its dependencies) for the given Python version.

For a full list of available packages for Python, type:

port list | grep py26-

OR

port list | grep py30-

Which command you use depends on which version of Python you chose to install.


回答 3

我使用MacPorts将Python和MacPorts跟踪的任何第三方模块/opt/local安装到中,并且将任何手动安装的模块(不在MacPorts存储库中的模块)安装到中/usr/local,这从来没有引起任何问题。我认为您可能对某些MacPorts脚本和环境变量的使用感到困惑。

MacPorts python_select用于选择“当前”版本的Python,但与模块无关。例如,这允许您使用MacPorts安装Python 2.5和Python 2.6,并在安装之间进行切换。

$PATH环境变量并没有影响Python模块被加载的内容。$PYTHONPATH是您要寻找的。$PYTHONPATH应该指向包含要加载的Python模块的目录。就我而言,我的$PYTHONPATH变量包含/usr/local/lib/python26/site-packages。如果您使用MacPorts的Python,它将为您设置其他适当的目录,因此您只需向添加其他路径$PYTHONPATH。但是同样,$PATH当Python搜索您已安装的模块时,根本不使用它。

$PATH 用于查找可执行文件,所以如果你安装的MacPorts’的Python,确保/opt/local/bin在你的$PATH

I use MacPorts to install Python and any third-party modules tracked by MacPorts into /opt/local, and I install any manually installed modules (those not in the MacPorts repository) into /usr/local, and this has never caused any problems. I think you may be confused as to the use of certain MacPorts scripts and environment variables.

MacPorts python_select is used to select the “current” version of Python, but it has nothing to do with modules. This allows you to, e.g., install both Python 2.5 and Python 2.6 using MacPorts, and switch between installs.

The $PATH environment variables does not affect what Python modules are loaded. $PYTHONPATH is what you are looking for. $PYTHONPATH should point to directories containing Python modules you want to load. In my case, my $PYTHONPATH variable contains /usr/local/lib/python26/site-packages. If you use MacPorts’ Python, it sets up the other proper directories for you, so you only need to add additional paths to $PYTHONPATH. But again, $PATH isn’t used at all when Python searches for modules you have installed.

$PATH is used to find executables, so if you install MacPorts’ Python, make sure /opt/local/bin is in your $PATH.


回答 4

使用MacPorts Python安装没有任何问题。如果要从MacPorts安装python模块,但看不到它们,则可能意味着您不调用安装的MacPorts python。在终端外壳中,您可以使用绝对路径来调用可能安装的各种Python。例如:

$ /usr/bin/python2.5         # Apple-supplied 2.5 (Leopard)
$ /opt/local/bin/python2.5   # MacPorts 2.5
$ /opt/local/bin/python2.6   # MacPorts 2.6
$ /usr/local/bin/python2.6   # python.org (MacPython) 2.6
$ /usr/local/bin/python3.1   # python.org (MacPython) 3.1

要在默认情况下获取正确的python,需要确保您的shell $ PATH设置正确,以确保首先找到正确的可执行文件。另一个解决方案是为各种python定义shell别名。

就像其他人建议的那样,也可以使用python.org(MacPython)安装。 easy_install 同样可以提供帮助,但是,由于每个Python实例可能都有自己的easy_install命令,因此请确保您调用的是right easy_install

There’s nothing wrong with using a MacPorts Python installation. If you are installing python modules from MacPorts but then not seeing them, that likely means you are not invoking the MacPorts python you installed to. In a terminal shell, you can use absolute paths to invoke the various Pythons that may be installed. For example:

$ /usr/bin/python2.5         # Apple-supplied 2.5 (Leopard)
$ /opt/local/bin/python2.5   # MacPorts 2.5
$ /opt/local/bin/python2.6   # MacPorts 2.6
$ /usr/local/bin/python2.6   # python.org (MacPython) 2.6
$ /usr/local/bin/python3.1   # python.org (MacPython) 3.1

To get the right python by default requires ensuring your shell $PATH is set properly to ensure that the right executable is found first. Another solution is to define shell aliases to the various pythons.

A python.org (MacPython) installation is fine, too, as others have suggested. easy_install can help but, again, because each Python instance may have its own easy_install command, make sure you are invoking the right easy_install.


回答 5

如果您从MacPorts使用Python,则它具有自己的easy_install,位于:/opt/local/bin/easy_install-2.6(对于py26而言)。这与简单地直接调用easy_install不同,即使您使用python_select更改了默认的python命令也是如此。

If you use Python from MacPorts, it has it’s own easy_install located at: /opt/local/bin/easy_install-2.6 (for py26, that is). It’s not the same one as simply calling easy_install directly, even if you used python_select to change your default python command.


回答 6

您有没有研究过easy_install?它不会同步您的macports或类似的东西,但是会自动下载最新的软件包和所有必要的依赖项,即

easy_install nose

用于鼻子单元测试包,或

easy_install trac

对于tracbug跟踪系统。

他们的EasyInstall页面上也有更多信息。

Have you looked into easy_install at all? It won’t synchronize your macports or anything like that, but it will automatically download the latest package and all necessary dependencies, i.e.

easy_install nose

for the nose unit testing package, or

easy_install trac

for the trac bug tracker.

There’s a bit more information on their EasyInstall page too.


回答 7

对于MacPython安装,我在此博客文章中找到了一种用于解决setuptools(easy_install)问题的有效解决方案:

http://droidism.com/getting-running-with-django-and-macpython-26-on-leopard

一个方便的技巧包括找出终端中哪个版本的python是活动的:

which python

For MacPython installations, I found an effective solution to fixing the problem with setuptools (easy_install) in this blog post:

http://droidism.com/getting-running-with-django-and-macpython-26-on-leopard

One handy tip includes finding out which version of python is active in the terminal:

which python

回答 8

使用MacPorts安装模块时,它不会进入Apple的Python版本。而是将这些模块安装到所选的MacPorts版本的Python中。

您可以使用名为python_select的mac端口更改默认使用的Python版本。这里的说明。

另外,还有easy_install。它将使用python安装python模块。

When you install modules with MacPorts, it does not go into Apple’s version of Python. Instead those modules are installed onto the MacPorts version of Python selected.

You can change which version of Python is used by default using a mac port called python_select. instructions here.

Also, there’s easy_install. Which will use python to install python modules.


回答 9

您可能已经pip3预先安装了,请尝试一下!

You may already have pip3 pre-installed, so just try it!


回答 10

关于使用哪个python版本,Mac OS通常会附带一个旧版本的python。升级到新版本是一个好主意。您可以从http://www.python.org/download/下载.dmg 。如果这样做,请记住更新路径。您可以在此处找到确切的命令http://farmdev.com/thoughts/66/python-3-0-on-mac-os-x-alongside-2-6-2-5-etc-/

Regarding which python version to use, Mac OS usually ships an old version of python. It’s a good idea to upgrade to a newer version. You can download a .dmg from http://www.python.org/download/ . If you do that, remember to update the path. You can find the exact commands here http://farmdev.com/thoughts/66/python-3-0-on-mac-os-x-alongside-2-6-2-5-etc-/


回答 11

我将easy_install与Apple的Python配合使用,它的工作原理很吸引人。

I use easy_install with Apple’s Python, and it works like a charm.


回答 12

直接安装其中一个fink软件包(2013年11月开始的Django 1.6)

fink install django-py27
fink install django-py33

或者创建一个虚拟环境:

fink install virtualenv-py27
virtualenv django-env
source django-env/bin/activate
pip install django
deactivate # when you are done

或者在virtualenv中使用fink django以及任何其他pip安装的软件包

fink install django-py27
fink install virtualenv-py27
virtualenv django-env --system-site-packages
source django-env/bin/activate
# django already installed
pip install django-analytical # or anything else you might want
deactivate # back to your normally scheduled programming

Directly install one of the fink packages (Django 1.6 as of 2013-Nov)

fink install django-py27
fink install django-py33

Or create yourself a virtualenv:

fink install virtualenv-py27
virtualenv django-env
source django-env/bin/activate
pip install django
deactivate # when you are done

Or use fink django plus any other pip installed packages in a virtualenv

fink install django-py27
fink install virtualenv-py27
virtualenv django-env --system-site-packages
source django-env/bin/activate
# django already installed
pip install django-analytical # or anything else you might want
deactivate # back to your normally scheduled programming

有关使用Google App Engine的反馈?[关闭]

问题:有关使用Google App Engine的反馈?[关闭]

希望做一个非常小,快速而又肮脏的项目。我喜欢Google App Engine在Python上运行并内置Django的事实-给我借口尝试该平台…但是我的问题是:

除了玩具问题以外,还有人利用App Engine处理其他事情吗?我看到了一些很好的示例应用程序,因此我认为这对于真实交易来说已经足够了,但是我想获得一些反馈。

任何其他成功/失败记录都很棒。

Looking to do a very small, quick ‘n dirty side project. I like the fact that the Google App Engine is running on Python with Django built right in – gives me an excuse to try that platform… but my question is this:

Has anyone made use of the app engine for anything other than a toy problem? I see some good example apps out there, so I would assume this is good enough for the real deal, but wanted to get some feedback.

Any other success/failure notes would be great.


回答 0

我已经为小型地震监视应用程序http://quakewatch.appspot.com/尝试了应用引擎

我的目的是查看应用程序引擎的功能,因此主要要点:

  1. 默认情况下,它不是Django附带的,它有自己的Web框架,它是pythonic的,具有像Django这样的URL调度程序,并且使用Django模板。因此,如果您有Django exp。您会发现它易于使用
  2. 您无法在服务器上执行任何长时间运行的进程,您要做的就是回复请求,并且应该很快,否则appengine会杀死它。因此,如果您的应用程序需要大量后端处理,则appengine不是最佳方法,否则您将不得不进行处理在您自己的服务器上
  3. 我的quakewatch应用程序具有订阅功能,这意味着我必须通过电子邮件将最新的地震发生,但是我无法在app引擎中运行后台进程来监视新的地震解决方案,这里是使用像pingablity.com这样的第三方服务,连接到您的页面之一并执行订阅电子邮件程序,但是在这里您还必须注意不要在这里花费太多时间或将任务分成几部分
  4. 它提供了类似于Django的建模功能,但后端完全不同,但是对于新项目而言,这并不重要。

但是总的来说,我认为这对于创建不需要大量后台处理的应用程序非常有用。

编辑:现在,任务队列可用于运行批处理或计划的任务

编辑:在GAE上工作/创建一个真实的应用程序一年之后,现在我的看法是,除非您要开发需要扩展到数百万用户的应用程序,否则请不要使用GAE。由于具有分布式特性,因此在GAE中维护和执行琐碎的任务是一件令人头疼的事情,为了避免超出期限,错误地计数实体或执行复杂的查询需要复杂的代码,因此小型复杂的应用程序应坚持使用LAMP。

编辑:模型应该特别考虑到您将来希望进行的所有交易而设计,因为只能在同一实体组中的实体可以在交易中使用,并且这使得更新两个不同组的过程成为噩梦,例如将资金从user1转移到user2除非它们在同一个实体组中,否则不可能在事务中进行交易,但是对于频繁更新而言,使它们成为同一实体组可能不是最好的….阅读此http://blog.notdot.net/2009/9/Distributed-Transactions-应用引擎

I have tried app engine for my small quake watch application http://quakewatch.appspot.com/

My purpose was to see the capabilities of app engine, so here are the main points:

  1. it doesn’t come by default with Django, it has its own web framework which is pythonic has URL dispatcher like Django and it uses Django templates So if you have Django exp. you will find it easy to use
  2. You can not execute any long running process on server, what you do is reply to request and which should be quick otherwise appengine will kill it So if your app needs lots of backend processing appengine is not the best way otherwise you will have to do processing on a server of your own
  3. My quakewatch app has a subscription feature, it means I had to email latest quakes as they happend, but I can not run a background process in app engine to monitor new quakes solution here is to use a third part service like pingablity.com which can connect to one of your page and which executes the subscription emailer but here also you will have to take care that you don’t spend much time here or break task into several pieces
  4. It provides Django like modeling capabilities but backend is totally different but for a new project it should not matter.

But overall I think it is excellent for creating apps which do not need lot of background processing.

Edit: Now task queues can be used for running batch processing or scheduled tasks

Edit: after working/creating a real application on GAE for a year, now my opnion is that unless you are making a application which needs to scale to million and million of users, don’t use GAE. Maintaining and doing trivial tasks in GAE is a headache due to distributed nature, to avoid deadline exceeded errors, count entities or do complex queries requires complex code, so small complex application should stick to LAMP.

Edit: Models should be specially designed considering all the transactions you wish to have in future, because entities only in same entity group can be used in a transaction and it makes the process of updating two different groups a nightmare e.g. transfer money from user1 to user2 in transaction is impossible unless they are in same entity group, but making them same entity group may not be best for frequent update purposes…. read this http://blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine


回答 1

我正在使用GAE托管多个高流量应用程序。大约为50-100 req / sec。太好了,我不能推荐它。

我以前的Web开发经验是使用Ruby(Rails / Merb)。学习Python很容易。我并没有弄乱Django或Pylons或任何其他框架,只是从GAE示例开始,并从提供的基本webapp库中构建了我需要的东西。

如果您习惯了SQL的灵活性,那么数据存储区可能需要一些时间来适应。没什么太伤人的!最大的调整是远离JOIN。您必须摆脱标准化是至关重要的想法。

I am using GAE to host several high-traffic applications. Like on the order of 50-100 req/sec. It is great, I can’t recommend it enough.

My previous experience with web development was with Ruby (Rails/Merb). Learning Python was easy. I didn’t mess with Django or Pylons or any other framework, just started from the GAE examples and built what I needed out of the basic webapp libraries that are provided.

If you’re used to the flexibility of SQL the datastore can take some getting used to. Nothing too traumatic! The biggest adjustment is moving away from JOINs. You have to shed the idea that normalizing is crucial.

Ben


回答 2

我使用Google App Engine的令人信服的原因之一是它与您所在域的Google Apps集成。从本质上讲,它允许您创建自定义的托管Web应用程序,这些应用程序仅限于您域的(受控)登录名。

我在这段代码中的大部分经验是构建一个简单的时间/任务跟踪应用程序。模板引擎很简单,但是使多页应用程序非常容易上手。登录/用户意识api同样有用。我能够创建一个公共页面/私有页面范例而没有太多问题。(用户将登录以查看私有页面。仅向匿名用户显示公共页面。)

当我因从事“实际工作”而离开时,我只是进入项目的数据存储部分。

我能够在极短的时间内完成很多工作(尚未完成)。因为我以前从未使用过Python,所以这特别令人愉快(既因为这对我来说是一种新语言,也因为尽管使用了新语言,但开发仍然非常快)。我碰到的很少,使我相信我将无法完成任务。相反,我对功能和特性有一个相当积极的印象。

这就是我的经验。也许它不仅仅代表未完成的玩具项目,还代表对平台的知情试用,我希望能有所帮助。

One of the compelling reasons I have come across for using Google App Engine is its integration with Google Apps for your domain. Essentially it allows you to create custom, managed web applications that are restricted to the (controlled) logins of your domain.

Most of my experience with this code was building a simple time/task tracking application. The template engine was simple and yet made a multi-page application very approachable. The login/user awareness api is similarly useful. I was able to make a public page/private page paradigm without too much issue. (a user would log in to see the private pages. An anonymous user was only shown the public page.)

I was just getting into the datastore portion of the project when I got pulled away for “real work”.

I was able to accomplish a lot (it still is not done yet) in a very little amount of time. Since I had never used Python before, this was particularly pleasant (both because it was a new language for me, and also because the development was still fast despite the new language). I ran into very little that led me to believe that I wouldn’t be able to accomplish my task. Instead I have a fairly positive impression of the functionality and features.

That is my experience with it. Perhaps it doesn’t represent more than an unfinished toy project, but it does represent an informed trial of the platform, and I hope that helps.


回答 3

“运行Django的App Engine”的想法有点误导。App Engine取代了整个Django模型层,因此准备花一些时间适应App Engine的数据存储,这需要以不同的方式建模和思考数据。

The “App Engine running Django” idea is a bit misleading. App Engine replaces the entire Django model layer so be prepared to spend some time getting acclimated with App Engine’s datastore which requires a different way of modeling and thinking about data.


回答 4

我用GAE建立了http://www.muspy.com

它不仅是一个玩具项目,而且也不过分复杂。我仍然依赖于Google可以解决的一些问题,但是整体开发网站是一种令人愉快的体验。

如果您不想处理托管问题,服务器管理等问题,绝对可以推荐。特别是如果您已经了解Python和Django。

I used GAE to build http://www.muspy.com

It’s a bit more than a toy project but not overly complex either. I still depend on a few issues to be addressed by Google, but overall developing the website was an enjoyable experience.

If you don’t want to deal with hosting issues, server administration, etc, I can definitely recommend it. Especially if you already know Python and Django.


回答 5

我认为,对于小型项目,App Engine目前非常不错。有很多事情可以说,不必担心托管。该API还会引导您朝着构建可扩展应用程序的方向发展,这是一种很好的做法。

  • app-engine-patch是Django和App Engine之间的良好层,可启用auth应用程序及更多功能。
  • Google承诺在2008年底之前提供SLA和定价模型。
  • 请求必须在10秒内完成,对Web服务的子请求则需要在5秒内完成。这迫使您设计一个快速,轻量级的应用程序,将重要的处理工作卸载到其他平台(例如,托管服务或EC2实例)。
  • 更多语言即将推出!Google不会说:-)。我的钱接下来是Java。

I think App Engine is pretty cool for small projects at this point. There’s a lot to be said for never having to worry about hosting. The API also pushes you in the direction of building scalable apps, which is good practice.

  • app-engine-patch is a good layer between Django and App Engine, enabling the use of the auth app and more.
  • Google have promised an SLA and pricing model by the end of 2008.
  • Requests must complete in 10 seconds, sub-requests to web services required to complete in 5 seconds. This forces you to design a fast, lightweight application, off-loading serious processing to other platforms (e.g. a hosted service or an EC2 instance).
  • More languages are coming soon! Google won’t say which though :-). My money’s on Java next.

回答 6

这个问题已经被完全回答。哪个好 但是也许有一件事值得一提。google app引擎有一个eclipse ide插件,很高兴使用。

如果您已经使用Eclipse进行开发,您将对此感到非常高兴。

要在Google App Engine的网站上进行部署,我需要做的就是单击一个带有飞机徽标的小按钮-超级。

This question has been fully answered. Which is good. But one thing perhaps is worth mentioning. The google app engine has a plugin for the eclipse ide which is a joy to work with.

If you already do your development with eclipse you are going to be so happy about that.

To deploy on the google app engine’s web site all I need to do is click one little button – with the airplane logo – super.


回答 7

看一下sql游戏,它非常稳定,实际上将流量限制提高了一点,从而使其受到Google的限制。除了将App托管在其他人完全控制的服务器上之外,我没有看到关于App Engine的好消息。

Take a look the the sql game, it is very stable and actually pushed traffic limits at one point so that it was getting throttled by Google. I have seen nothing but good news about App Engine, other than hosting you app on servers someone else controls completely.


回答 8

我使用GAE构建了一个简单的应用程序,该应用程序接受一些参数,格式并发送电子邮件。这是非常简单和快速的。我还在GAE数据存储和内存缓存服务(http://dbaspects.blogspot.com/2010/01/memcache-vs-datastore-on-google-app.html)上做了一些性能基准测试。没有那么快。我认为GAE是执行特定方法的严肃平台。我认为它将演变为真正可扩展的平台,在该平台上根本不允许不良做法。

I used GAE to build a simple application which accepts some parameters, formats and send email. It was extremely simple and fast. I also made some performance benchmarks on the GAE datastore and memcache services (http://dbaspects.blogspot.com/2010/01/memcache-vs-datastore-on-google-app.html ). It is not that fast. My opinion is that GAE is serious platform which enforce certain methodology. I think it will evolve to the truly scalable platform, where bad practices simply not allowed.


回答 9

我将GAE用于我的Flash游戏网站Bearded Games。GAE是一个很棒的平台。我使用了Django模板,它比PHP过去要容易得多。它带有出色的管理面板,并为您提供了非常好的日志。数据存储区不同于MySQL之类的数据库,但是使用起来要容易得多。建立网站非常简单明了,他们在网站上有很多有用的建议。

I used GAE for my flash gaming site, Bearded Games. GAE is a great platform. I used Django templates which are so much easier than the old days of PHP. It comes with a great admin panel, and gives you really good logs. The datastore is different than a database like MySQL, but it’s much easier to work with. Building the site was easy and straightforward and they have lots of helpful advice on the site.


回答 10

我使用GAE和Django构建了Facebook应用程序。我以http://code.google.com/p/app-engine-patch作为起点,因为它具有Django 1.1支持。我没有尝试使用任何manage.py命令,因为我认为它们不起作用,但是我什至没有调查。该应用程序具有三个模型,还使用了pyfacebook,但这就是复杂程度。我正在构建一个更加复杂的应用程序,并开始在http://brianyamabe.com上发布博客。

I used GAE and Django to build a Facebook application. I used http://code.google.com/p/app-engine-patch as my starting point as it has Django 1.1 support. I didn’t try to use any of the manage.py commands because I assumed they wouldn’t work, but I didn’t even look into it. The application had three models and also used pyfacebook, but that was the extent of the complexity. I’m in the process of building a much more complicated application which I’m starting to blog about on http://brianyamabe.com.


四肢瘫痪程序员的最佳编程工具

问题:四肢瘫痪程序员的最佳编程工具

是的,这与编程有关,在您下结论之前。它涵盖了一种情况,“在那儿,但为了神的恩典,去你我吧。” 这对我来说是全新的领域,因此我在这里寻求一些认真的帮助。

高中毕业后的一个年轻人,洪萨里帕(Honza Ripa)在高中毕业后的两周里做了经典的愚蠢的事情-他潜入俄罗斯河的浅水区,并经历了C-4 / C-5中断,有时称为游泳。池休息。在短短的几秒钟内,他从一位杰出的高尔夫球手和摔跤手变成了四肢瘫痪的人。(读这个故事……我们所有人都应该很幸运能够拥有像Brianna这样的女朋友。)那是10个月前的事,他只恢复了对食指和另外两只手的少量控制/脚部动作,没有一个细粒度的。

他可以通过语音命令完全控制他的计算机(当前运行Win7,但我们可以根据需要进行更改)。洪za不傻 他的AP数学和物理平均分达到3.7。

问题:

  1. 由于他所有的输入都是通过语音命令进行的,因此他担心编程中特殊字符的占主导地位将需要大量的冗长命令。有谁知道专门为程序员设计的出色语音输入系统?我正在考虑某种可能是模态的东西-例如,您说“ Python输入”,并且它进入了用于进行类定义的宏模式,等等。鉴于程序员领域中的所有RSI,都必须有一些东西。它在什么操作系统上运行?

  2. 我正计划教他Python,这是我编程和教学的首选语言。是否有任何用Python编写的应用程序/工具,以及在支持他的智力支持他的残疾方面是否特别适合他?他表达的兴趣之一是对股票投资,但这可能不是一个崭新的程序员的良好起点。

  3. 许多环境(Flash,JavaScript等)对具有可访问性挑战的人不是特别友好。我隐约记得(但找不到)一个研究项目,该项目基本上在屏幕环境之上创建了一个覆盖系统,然后允许在屏幕图像之上构建宏命令。如果我们能够获得/培训该系统,我们也许可以消除使用网络的许多障碍。

  4. 我对寻找基于Python的开源机器人技术和机器人假体项目特别感兴趣,这样他就可以在学习解决自己的一些迫在眉睫的问题的同时,学习高级编程概念。

我已经对此进行了大量的搜索,但是我知道有些事情我缺少。我要求SO社区在这里加紧讨论。我知道这个小组有答案,所以让我听听!在这种改变生活的事件之后,我们所有人可能/仍然需要编程的机会使我不知所措

更新:我刚刚注册了Computingforquads.org,我将为各种问题的解决方案创建页面。到目前为止,感谢您的帮助,并始终保持这些答案!

Before you jump to conclusions, yes, this is programming related. It covers a situation that comes under the heading of, “There, but for the grace of God, go you or I.” This is brand new territory for me so I’m asking for some serious help here.

A young man, Honza Ripa, in a nearby town did the classic Dumb Thing two weeks after graduating from High School — he dove into shallow water in the Russian River and had a C-4/C-5 break, sometimes called a Swimming Pool break. In a matter of seconds he went from an exceptional golfer and wrestler to a quadriplegic. (Read the story … all of us should have been so lucky as to have a girlfriend like Brianna.) That was 10 months ago and he has regained only tiny amounts of control of his right index finger and a couple of other hand/foot motions, none of them fine-grained.

His total control of his computer (currently running Win7, but we can change that as needed) is via voice command. Honza’s not dumb. He had a 3.7 GPA with AP math and physics.

The Problems:

  1. Since all of his input is via voice command, he is concerned that the predominance of special characters in programming will require vast amount of verbose commands. Does anyone know of any well done voice input system specifically designed for programmers? I’m thinking about something that might be modal–e.g. you say “Python input” and it goes into a macro mode for doing class definitions, etc. Given all of the RSI in programmer-land there’s got to be something out there. What OS(es) does it run on?

  2. I am planning on teaching him Python, which is my preferred language for programming and teaching. Are there any applications / whatevers that are written in Python and would be a particularly good match for engaging him mentally while supporting his disability? One of his expressed interests is in stock investing, but that not might be a good starting point for a brand-new programmer.

  3. There are a lot of environments (Flash, JavaScript, etc) that are not particularly friendly to people with accessibility challenges. I vaguely remember (but cannot find) a research project that basically created an overlay system on top of a screen environment and then allowed macro command construction on top of the screen image. If we can get/train this system, we may be able to remove many hurdles to using the net.

  4. I am particularly interested in finding open source Python-based robotics and robotic prostheses projects so that he can simultaneously learn advanced programming concepts while learning to solve some of his own immediate problems.

I’ve done a ton of googling on this, but I know there are things I’m missing. I’m asking the SO community to step up to the plate here. I know this group has the answers, so let me hear them! Overwhelm me with the opportunities that any of us might have/need to still program after such a life-changing event.

Update: I just registered computingforquads.org and I’ll be creating pages for all sorts of solutions to all sorts of problems. Thanks for you help so far and keep those answers coming!


回答 0

我有运动损伤,在没有严重疼痛的情况下,我不能输入多个字符。

相反,我将emacs与Dragon NaturallySpeaking结合使用。我已经编写了宏和脚本来帮助实现它。该系统并不完美,但可以正常工作。我主要使用C ++进行编程,但我也使用python。

如果您愿意,我会帮助您。我必须警告您,习惯几个月的时间来对文本软件进行语音训练和培训需要花费几个月的时间。此外,我不是英语为母语的人,请确保不会妨碍您

不要失望,有解决方案。

这里是emacs和Dragon文件的链接(不幸的是尚未记录)

http://code.google.com/p/asadchev/source/browse/#svn/trunk/home/Dragon

http://code.google.com/p/asadchev/source/browse/#svn/trunk/emacs/elisp

另外,如果您需要更多信息,我的电话是515 230 9363(美国,爱荷华州)。如果可以的话,我很乐意为您提供帮助

I have sports injuries, and I cannot type more than few characters without serious pain.

Instead, I use emacs together with Dragon NaturallySpeaking. I have written macros and scripts to help it get by. The system is not perfect, but it works. I program mostly in C++, but I also use python.

If you want to, I will help you with that. I have to warn you, it takes few months to get used to speech to text software and train it. moreover, I am not native English speaker, am sure that gets in the way

Do not despair, there are solutions.

here a link to emacs and Dragon files (unfortunately have not documented yet)

http://code.google.com/p/asadchev/source/browse/#svn/trunk/home/Dragon

http://code.google.com/p/asadchev/source/browse/#svn/trunk/emacs/elisp

also, if you need more info, my number is 515 230 9363 (United States, Iowa). I will be glad to help you if I can


回答 1

值得一看的是Dasher Project,它使即使是严重残疾的人也可以合理快速地输入文本。Dasher建立在语言的概率模型上,因此更可能的语音更容易输入到系统中。该演示系统附带了相当令人印象深刻的自然语言集合。获得使用Python编写的大型程序主体,将主体装入Dasher并创建用于输入Python程序的专用版本应该很容易。

It’s worth looking at the Dasher Project, which makes it possible to enter text reasonably quickly even for the severly disabled. Dasher is built on a probabilistic model of languages, so that more likely utterances are easier to enter into the system. The demonstration system comes with a fairly impressive collection of natural languages. It should be easy to get a large corpus of programs written in Python, load Dasher with the corpus, and create a special-purpose version for entering Python programs.


回答 2

这不是任何专业软件的一部分,但是当我看到此内容时,我认为使用眼睛移动跟踪或最小限度的鼠标移动输入文本会很有用。请参阅Ken Perlin的“处理”页面,并查看“笔输入”的小程序。

This isn’t part of any professional software, but when I saw this, I’ve thought it would be good for text entry using eye movement tracking or minimal mouse movement. See Ken Perlin’s Processing page, and look at the applets for “pen input”.


回答 3

我认识印度某村庄的某人截瘫,他使用《龙语》来朗读文字软件在她的计算机上书写。我不知道它对程序员(她不是程序员)有多适合,但这只是一个开始。

您可能还需要研究Natural Point。这是一只眼睛控制的鼠标,可能会对Honza有所帮助

希望这可以帮助

I know someone in a village in India who is a paraplegic, who uses Dragon Speech to Text software to write on her computer. I don’t know how well suited it is for a programmer (she is not a programmer), but it’s a start.

You might also want to look into Natural Point. It’s an eye controlled mouse, which might help Honza

Hope this helps


回答 4

iPython完成

在python方面,iPython显示参数,函数等,并具有命令完成功能。也许还可以对其进行定制以响应各种输入设备?

http://ipython.scipy.org/moin/

iPython with completion

On the python side, iPython shows parameters, functions, etc, and has command completion. Perhaps it could also be customized to respond to the various input devices as well?

http://ipython.scipy.org/moin/


回答 5

可能有帮助的一件事(我从这个问题中得到了帮助)是http://shorttalk-emacs.sourceforge.net/。它似乎是emacs和语音识别之间的接口。关于语言,我建议在Python上使用Lua。它具有更自然的英语流。

One thing that may help (i got it from this question) is http://shorttalk-emacs.sourceforge.net/ . It seems to be an interface between emacs and speech recognition. And regarding languages, i would recommend using Lua over Python. It has a more natural English flow to it.


回答 6

我知道这个问题现在已经很老了。我不知道Honza在编程方面的情况如何。很高兴听到回覆。

就其价值而言,我遭受了RSI的困扰,现在尝试尽量减少键盘,尤其是鼠标的使用。

我自己的语音识别经验是,这些东西确实可以工作。我使用Windows内置的Windows 7(WSR)语音识别软件。我还使用了语音手指(http://voicefinger.cozendey.com/)来帮助移动鼠标指针。我要提到的一些关键点是:

了解捷径。您几乎可以使用快捷方式执行任何操作,并且在“键入模式”下使用语音识别可以说出效果很好(请参见下文)。

使用键入模式。除非您要口述文本,否则这对于说出计算机的捷径或拼写奇怪的单词非常有用。有趣的是,它不是WSR的明确“宣传”功能。

语音字母。要充分利用打字模式,请学习语音字母:http : //en.wikipedia.org/wiki/NATO_phonetic_alphabet 在使用任何形式的语音识别功能时,如果没有这一点,您将无法实现。

VIM。(或emacs,我猜-不确定)。Vim非常适合编辑文本,而无需触摸鼠标。这非常适合使用WSR编辑文本。我本人只是VIM初学者,但发现它非常有用。

网页浏览。以我的经验,没有鼠标,网页浏览仍然是一件非常困难的事情。有太多情况需要您将鼠标悬停才能到达基本命令。这真是太可惜了。尽管如此,还是有一些非常好的Firefox插件可以帮助您无需鼠标即可浏览。

  1. 无鼠标浏览:https ://addons.mozilla.org/en-us/firefox/addon/mouseless-browsing/ 这是一个简洁的小工具,具有许多配置选项,可将数字置于所有链接的旁边。然后,您可以输入这些数字来激活链接
  2. Vimperator:http : //vimperator.org/ 这比无鼠标浏览要走得更多。基本上,它为您提供了完整的vim,如控制Firefox。我发现这比无鼠标浏览更好,但是在更改默认Firefox行为的情况下可能会令人讨厌。

这些只是我个人的经历。很高兴听到Honza的工作进展。

I know this question is quite old now. I wonder how things are going for Honza with respect to programming. It would be nice to hear back.

For what it’s worth, I suffer from RSI and now try to minimize use of the keyboard and especially the mouse.

My own experience of voice recognition is that this stuff DOES work. I use Windows’s inbuilt speech recognition software for Windows 7 (WSR). I’ve also used voice finger (http://voicefinger.cozendey.com/) to help move the mouse pointer. Some key points I would mention are:

Learn the shortcuts. You can do almost anything using shortcuts and speaking them works great using Voice Recognition when in “typing mode” (see below).

Use Typing mode. Unless you are dictating text this is great for speaking short cuts to the computer or for spelling weird words. Interestingly it is not a clearly “advertised” function of WSR.

Phonetic Alphabet. To make good use of typing mode learn the phonetic alphabet: http://en.wikipedia.org/wiki/NATO_phonetic_alphabet You can’t realistically get by without this when using any form of speech recognition.

VIM. (or emacs I guess – not sure). Vim is a great for editing text without touching the mouse – ever. This makes it great for editing texts using WSR. I am only a VIM beginner myself but find it incredibly helpful.

Web browsing. In my experience web browsing is still an extremely difficult thing to do without a mouse. There are simply too many situations which require you to hover with the mouse in order to get to the underlying commands. This is a great shame. Nevertheless there are some really good Firefox plugins to help browsing without a mouse.

  1. Mouseless browsing: https://addons.mozilla.org/en-us/firefox/addon/mouseless-browsing/ This is a neat little tool with lots of configuration options for putting numbers next to all links. You can then type these numbers to activate the link
  2. Vimperator: http://vimperator.org/ This goes quite a lot further than mouseless browsing. It basically gives you complete vim like control of firefox. I find this works better than mouseless browsing, but can be annoying in instances where it changes default Firefox behavious.

These are just my own personal experiences. It would be great to hear back about how Honza is getting on.


如何在Python3中像printf一样打印?

问题:如何在Python3中像printf一样打印?

在Python 2中,我使用了:

print "a=%d,b=%d" % (f(x,n),g(x,n))

我试过了:

print("a=%d,b=%d") % (f(x,n),g(x,n))

In Python 2 I used:

print "a=%d,b=%d" % (f(x,n),g(x,n))

I’ve tried:

print("a=%d,b=%d") % (f(x,n),g(x,n))

回答 0

在Python2中,print是一个引入了以下语句的关键字:

print "Hi"

在Python3中,print是可以调用的函数:

print ("Hi")

在这两个版本中,%都是一个运算符,它在左侧需要一个字符串,在右侧需要一个值或一个值的元组或一个映射对象(如dict)。

因此,您的行应如下所示:

print("a=%d,b=%d" % (f(x,n),g(x,n)))

另外,对于Python3和更高版本,建议使用{}-style格式而不是%-style格式:

print('a={:d}, b={:d}'.format(f(x,n),g(x,n)))

Python 3.6引入了另一种字符串格式范例:f-strings

print(f'a={f(x,n):d}, b={g(x,n):d}')

In Python2, print was a keyword which introduced a statement:

print "Hi"

In Python3, print is a function which may be invoked:

print ("Hi")

In both versions, % is an operator which requires a string on the left-hand side and a value or a tuple of values or a mapping object (like dict) on the right-hand side.

So, your line ought to look like this:

print("a=%d,b=%d" % (f(x,n),g(x,n)))

Also, the recommendation for Python3 and newer is to use {}-style formatting instead of %-style formatting:

print('a={:d}, b={:d}'.format(f(x,n),g(x,n)))

Python 3.6 introduces yet another string-formatting paradigm: f-strings.

print(f'a={f(x,n):d}, b={g(x,n):d}')

回答 1

最推荐的方法是使用format方法。在这里了解更多

a, b = 1, 2

print("a={0},b={1}".format(a, b))

The most recommended way to do is to use format method. Read more about it here

a, b = 1, 2

print("a={0},b={1}".format(a, b))

回答 2

来自O’Reilly的Python Cookbook的简单printf()函数。

import sys
def printf(format, *args):
    sys.stdout.write(format % args)

输出示例:

i = 7
pi = 3.14159265359
printf("hi there, i=%d, pi=%.2f\n", i, pi)
# hi there, i=7, pi=3.14

Simple printf() function from O’Reilly’s Python Cookbook.

import sys
def printf(format, *args):
    sys.stdout.write(format % args)

Example output:

i = 7
pi = 3.14159265359
printf("hi there, i=%d, pi=%.2f\n", i, pi)
# hi there, i=7, pi=3.14

回答 3

Python 3.6引入了用于内联插值的f字符串。更好的是,它扩展了语法,还允许使用插值的格式说明符。我在Google上搜索时一直在努力的工作(并遇到了这个老问题!):

print(f'{account:40s} ({ratio:3.2f}) -> AUD {splitAmount}')

PEP 498包含详细信息。而且…它用其他语言的格式说明符排序了我的烦恼-允许说明符本身可以是表达式!好极了!请参阅:格式说明符

Python 3.6 introduced f-strings for inline interpolation. What’s even nicer is it extended the syntax to also allow format specifiers with interpolation. Something I’ve been working on while I googled this (and came across this old question!):

print(f'{account:40s} ({ratio:3.2f}) -> AUD {splitAmount}')

PEP 498 has the details. And… it sorted my pet peeve with format specifiers in other langs — allows for specifiers that themselves can be expressions! Yay! See: Format Specifiers.


回答 4

简单的例子:

print("foo %d, bar %d" % (1,2))

Simple Example:

print("foo %d, bar %d" % (1,2))


回答 5

一个简单的。

def printf(format, *values):
    print(format % values )

然后:

printf("Hello, this is my name %s and my age %d", "Martin", 20)

A simpler one.

def printf(format, *values):
    print(format % values )

Then:

printf("Hello, this is my name %s and my age %d", "Martin", 20)

回答 6

因为您%print(...)括号之外,所以您试图将变量插入到调用结果printprint(...)返回None,所以这将不起作用,还有一个小问题,您已经在这个时间和时间旅行中打印了模板,这是我们所居住的宇宙定律所禁止的。

你想整个事情进行打印,包括%和它的操作数,需要为内部print(...)通话,从而使打印之前它的字符串可以建成。

print( "a=%d,b=%d" % (f(x,n), g(x,n)) )

我添加了一些额外的空格以使其更清晰(尽管它们不是必需的,通常也不认为是好的样式)。

Because your % is outside the print(...) parentheses, you’re trying to insert your variables into the result of your print call. print(...) returns None, so this won’t work, and there’s also the small matter of you already having printed your template by this time and time travel being prohibited by the laws of the universe we inhabit.

The whole thing you want to print, including the % and its operand, needs to be inside your print(...) call, so that the string can be built before it is printed.

print( "a=%d,b=%d" % (f(x,n), g(x,n)) )

I have added a few extra spaces to make it clearer (though they are not necessary and generally not considered good style).


回答 7

python中没有其他的printf单词…我很惊讶!最好的代码是

def printf(format, *args):
    sys.stdout.write(format % args)

由于这种形式不允许打印\ n。其他所有人都没有。这就是为什么打印不好的原因。而且,您还需要以特殊形式编写args。上面的功能没有缺点。这是printf函数的标准常用形式。

Other words printf absent in python… I’m surprised! Best code is

def printf(format, *args):
    sys.stdout.write(format % args)

Because of this form allows not to print \n. All others no. That’s why print is bad operator. And also you need write args in special form. There is no disadvantages in function above. It’s a standard usual form of printf function.


回答 8

print("Name={}, balance={}".format(var-name, var-balance))
print("Name={}, balance={}".format(var-name, var-balance))

“ mro()”有什么作用?

问题:“ mro()”有什么作用?

django.utils.functional.py

for t in type(res).mro():  # <----- this
    if t in self.__dispatch:
        return self.__dispatch[t][funcname](res, *args, **kw)

我不明白mro()。它是做什么的,“ mro”是什么意思?

In django.utils.functional.py:

for t in type(res).mro():  # <----- this
    if t in self.__dispatch:
        return self.__dispatch[t][funcname](res, *args, **kw)

I don’t understand mro(). What does it do and what does “mro” mean?


回答 0

跟着…:

>>> class A(object): pass
... 
>>> A.__mro__
(<class '__main__.A'>, <type 'object'>)
>>> class B(A): pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
>>> class C(A): pass
... 
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
>>> 

只要我们具有单一继承,__mro__它就只是该类的元组:类,其基础,其基础的基础,依此类推object(当然,仅适用于新型类)。

现在,具有多重继承…:

>>> class D(B, C): pass
... 
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

…您还可以确保,在中__mro__,没有类被重复,并且没有类在其祖先之后出现,除了首先进入相同多重继承级别的类(如本例中的B和C)之外,__mro__左到右。

从类的实例(而不是方法)获得的每个属性在概念上都会沿进行查找__mro__,因此,如果祖先中有多个类定义了该名称,则可以告诉您在哪里可以找到该属性-在第一个类中在__mro__定义该名称。

Follow along…:

>>> class A(object): pass
... 
>>> A.__mro__
(<class '__main__.A'>, <type 'object'>)
>>> class B(A): pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
>>> class C(A): pass
... 
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
>>> 

As long as we have single inheritance, __mro__ is just the tuple of: the class, its base, its base’s base, and so on up to object (only works for new-style classes of course).

Now, with multiple inheritance…:

>>> class D(B, C): pass
... 
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

…you also get the assurance that, in __mro__, no class is duplicated, and no class comes after its ancestors, save that classes that first enter at the same level of multiple inheritance (like B and C in this example) are in the __mro__ left to right.

Every attribute you get on a class’s instance, not just methods, is conceptually looked up along the __mro__, so, if more than one class among the ancestors defines that name, this tells you where the attribute will be found — in the first class in the __mro__ that defines that name.


回答 1

mro()代表方法解析顺序。它以搜索方法的顺序返回类派生的类型的列表。

mro()__mro__仅适用于新样式类。在python 3中,它们可以正常工作。但是在python 2中,这些类需要从继承object

mro() stands for Method Resolution Order. It returns a list of types the class is derived from, in the order they are searched for methods.

mro() or __mro__ works only on new style classes. In python 3, they work without any issues. But in python 2 those classes need to inherit from object.


回答 2

这也许会显示解决的顺序。

class A(object):
    def dothis(self):
        print('I am from A class')

class B(A):
    pass

class C(object):
    def dothis(self):
        print('I am from C class')

class D(B, C):
    pass

d_instance= D()
d_instance.dothis()
print(D.mro())

和响应将是

I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]

该规则是深度优先的,在这种情况下,其含义是D,B,A,C。

在搜索继承的类时,Python通常使用深度优先的顺序,但是当两个类从同一个类继承时,Python将从mro中删除对该类的首次提及。

This would perhaps show the order of resolution.

class A(object):
    def dothis(self):
        print('I am from A class')

class B(A):
    pass

class C(object):
    def dothis(self):
        print('I am from C class')

class D(B, C):
    pass

d_instance= D()
d_instance.dothis()
print(D.mro())

and response would be

I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]

The rule is depth-first, which in this case would mean D, B, A, C.

Python normally uses a depth-first order when searching inheriting classes, but when two classes inherit from the same class, Python removes the first mention of that class from mro.


回答 3

钻石继承的解决顺序将有所不同。

class A(object):
    def dothis(self):
        print('I am from A class')


class B1(A):
    def dothis(self):
        print('I am from B1 class')
    # pass


class B2(object):
    def dothis(self):
        print('I am from B2 class')
    # pass


class B3(A):
    def dothis(self):
        print('I am from B3 class')


# Diamond inheritance
class D1(B1, B3):
    pass


class D2(B1, B2):
    pass


d1_instance = D1()
d1_instance.dothis()
# I am from B1 class
print(D1.__mro__)
# (<class '__main__.D1'>, <class '__main__.B1'>, <class '__main__.B3'>, <class '__main__.A'>, <class 'object'>)


d2_instance = D2()
d2_instance.dothis()
# I am from B1 class
print(D2.__mro__)
# (<class '__main__.D2'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)

Order of resolution will be different in diamond inheritance.

class A(object):
    def dothis(self):
        print('I am from A class')


class B1(A):
    def dothis(self):
        print('I am from B1 class')
    # pass


class B2(object):
    def dothis(self):
        print('I am from B2 class')
    # pass


class B3(A):
    def dothis(self):
        print('I am from B3 class')


# Diamond inheritance
class D1(B1, B3):
    pass


class D2(B1, B2):
    pass


d1_instance = D1()
d1_instance.dothis()
# I am from B1 class
print(D1.__mro__)
# (<class '__main__.D1'>, <class '__main__.B1'>, <class '__main__.B3'>, <class '__main__.A'>, <class 'object'>)


d2_instance = D2()
d2_instance.dothis()
# I am from B1 class
print(D2.__mro__)
# (<class '__main__.D2'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)

在Windows和Mac OS中都使用Python中的默认OS应用程序打开文档

问题:在Windows和Mac OS中都使用Python中的默认OS应用程序打开文档

我需要能够使用Windows和Mac OS中的默认应用程序打开文档。基本上,我想做的事情与您在资源管理器或Finder中双击文档图标时发生的事情相同。用Python做到这一点的最佳方法是什么?

I need to be able to open a document using its default application in Windows and Mac OS. Basically, I want to do the same thing that happens when you double-click on the document icon in Explorer or Finder. What is the best way to do this in Python?


回答 0

openstart分别是Mac OS / X和Windows的命令解释器。

要从Python调用它们,可以使用subprocessmodule或os.system()

以下是有关使用哪个软件包的注意事项:

  1. 您可以通过调用给他们os.system,该电话有效,但是…

    转义: os.system仅适用于路径名中没有空格或其他shell元字符的文件名(例如A:\abc\def\a.txt),否则需要转义。有shlex.quote针对Unix的系统,但没有Windows的真正标准。也许还会看到python,windows:用shlex解析命令行

    • MacOS / X: os.system("open " + shlex.quote(filename))
    • Windows:也应避免os.system("start " + filename)在适当的地方说话filename
  2. 您也可以通过subprocess模块调用它们,但是…

    对于Python 2.7及更高版本,只需使用

    subprocess.check_call(['open', filename])

    在Python 3.5+中,您可以等效地使用稍微更复杂但也更通用的功能

    subprocess.run(['open', filename], check=True)

    如果您需要一直兼容Python 2.4,则可以使用subprocess.call()并实现自己的错误检查:

    try:
        retcode = subprocess.call("open " + filename, shell=True)
        if retcode < 0:
            print >>sys.stderr, "Child was terminated by signal", -retcode
        else:
            print >>sys.stderr, "Child returned", retcode
    except OSError, e:
        print >>sys.stderr, "Execution failed:", e

    现在,使用的好处是subprocess什么?

    • 安全性:从理论上讲,这是更安全的方法,但是实际上我们需要以一种或另一种方式执行命令行。在这两种环境中,我们都需要环境和服务来解释,获取路径等。在这两种情况下,我们都不执行任意文本,因此它没有固有的“但您可以键入'filename ; rm -rf /'”问题,并且如果文件名可以被破坏,则使用subprocess.call不会给我们带来更多的保护。
    • 错误处理:实际上并没有给我们提供更多的错误检测功能,retcode无论哪种情况我们都取决于 但是在错误的情况下显式引发异常的行为当然可以帮助您注意到是否存在故障(尽管在某些情况下,回溯可能根本不比简单地忽略错误更有用)。
    • 产生一个(非阻塞的)子流程:我们不需要等待子流程,因为我们通过问题陈述来启动一个单独的流程。

    反对“但subprocess首选”。但是,os.system()不建议弃用它,从某种意义上说,它是完成此特定工作的最简单工具。结论:os.system()因此使用也是正确的答案。

    明显的缺点是Windows start命令要求您传递shell=True,否定了使用的大多数好处subprocess

open and start are command-interpreter things for Mac OS/X and Windows respectively, to do this.

To call them from Python, you can either use subprocess module or os.system().

Here are considerations on which package to use:

  1. You can call them via os.system, which works, but…

    Escaping: os.system only works with filenames that don’t have any spaces or other shell metacharacters in the pathname (e.g. A:\abc\def\a.txt), or else these need to be escaped. There is shlex.quote for Unix-like systems, but nothing really standard for Windows. Maybe see also python, windows : parsing command lines with shlex

    • MacOS/X: os.system("open " + shlex.quote(filename))
    • Windows: os.system("start " + filename) where properly speaking filename should be escaped, too.
  2. You can also call them via subprocess module, but…

    For Python 2.7 and newer, simply use

    subprocess.check_call(['open', filename])
    

    In Python 3.5+ you can equivalently use the slightly more complex but also somewhat more versatile

    subprocess.run(['open', filename], check=True)
    

    If you need to be compatible all the way back to Python 2.4, you can use subprocess.call() and implement your own error checking:

    try:
        retcode = subprocess.call("open " + filename, shell=True)
        if retcode < 0:
            print >>sys.stderr, "Child was terminated by signal", -retcode
        else:
            print >>sys.stderr, "Child returned", retcode
    except OSError, e:
        print >>sys.stderr, "Execution failed:", e
    

    Now, what are the advantages of using subprocess?

    • Security: In theory, this is more secure, but in fact we’re needing to execute a command line one way or the other; in either environment, we need the environment and services to interpret, get paths, and so forth. In neither case are we executing arbitrary text, so it doesn’t have an inherent “but you can type 'filename ; rm -rf /'” problem, and if the file name can be corrupted, using subprocess.call gives us little additional protection.
    • Error handling: It doesn’t actually give us any more error detection, we’re still depending on the retcode in either case; but the behavior to explicitly raise an exception in the case of an error will certainly help you notice if there is a failure (though in some scenarios, a traceback might not at all be more helpful than simply ignoring the error).
    • Spawns a (non-blocking) subprocess: We don’t need to wait for the child process, since we’re by problem statement starting a separate process.

    To the objection “But subprocess is preferred.” However, os.system() is not deprecated, and it’s in some sense the simplest tool for this particular job. Conclusion: using os.system() is therefore also a correct answer.

    A marked disadvantage is that the Windows start command requires you to pass in shell=True which negates most of the benefits of using subprocess.


回答 1

使用subprocessPython 2.4+上可用的模块,而不要使用os.system(),因此您不必处理外壳转义。

import subprocess, os, platform
if platform.system() == 'Darwin':       # macOS
    subprocess.call(('open', filepath))
elif platform.system() == 'Windows':    # Windows
    os.startfile(filepath)
else:                                   # linux variants
    subprocess.call(('xdg-open', filepath))

双括号是因为subprocess.call()希望将序列作为其第一个参数,因此我们在这里使用元组。在具有Gnome的Linux系统上,还有一个gnome-open命令可以执行相同的操作,但是xdg-open它是Free Desktop Foundation标准,并且可以在Linux桌面环境中使用。

Use the subprocess module available on Python 2.4+, not os.system(), so you don’t have to deal with shell escaping.

import subprocess, os, platform
if platform.system() == 'Darwin':       # macOS
    subprocess.call(('open', filepath))
elif platform.system() == 'Windows':    # Windows
    os.startfile(filepath)
else:                                   # linux variants
    subprocess.call(('xdg-open', filepath))

The double parentheses are because subprocess.call() wants a sequence as its first argument, so we’re using a tuple here. On Linux systems with Gnome there is also a gnome-open command that does the same thing, but xdg-open is the Free Desktop Foundation standard and works across Linux desktop environments.


回答 2

我更喜欢:

os.startfile(path, 'open')

请注意,此模块支持在其文件夹和文件中带有空格的文件名,例如

A:\abc\folder with spaces\file with-spaces.txt

python docs)不必添加’open’(这是默认值)。文档特别提到这就像双击Windows资源管理器中的文件图标。

此解决方案仅适用于Windows。

I prefer:

os.startfile(path, 'open')

Note that this module supports filenames that have spaces in their folders and files e.g.

A:\abc\folder with spaces\file with-spaces.txt

(python docs) ‘open’ does not have to be added (it is the default). The docs specifically mention that this is like double-clicking on a file’s icon in Windows Explorer.

This solution is windows only.


回答 3

仅出于完整性考虑(这不是问题),xdg-open将在Linux上执行相同的操作。

Just for completeness (it wasn’t in the question), xdg-open will do the same on Linux.


回答 4

import os
import subprocess

def click_on_file(filename):
    '''Open document with default application in Python.'''
    try:
        os.startfile(filename)
    except AttributeError:
        subprocess.call(['open', filename])
import os
import subprocess

def click_on_file(filename):
    '''Open document with default application in Python.'''
    try:
        os.startfile(filename)
    except AttributeError:
        subprocess.call(['open', filename])

回答 5

如果必须使用启发式方法,则可以考虑webbrowser
它是标准库,尽管有其名称,它也会尝试打开文件:

请注意,在某些平台上,尝试使用此功能打开文件名可能有效并启动操作系统的关联程序。但是,这既不支持也不是可移植的。(参考

我尝试了这段代码,它在Windows 7和Ubuntu Natty中运行良好:

import webbrowser
webbrowser.open("path_to_file")

使用Internet Explorer 8,此代码在Windows XP Professional中也可以正常工作。

If you have to use an heuristic method, you may consider webbrowser.
It’s standard library and despite of its name it would also try to open files:

Note that on some platforms, trying to open a filename using this function, may work and start the operating system’s associated program. However, this is neither supported nor portable. (Reference)

I tried this code and it worked fine in Windows 7 and Ubuntu Natty:

import webbrowser
webbrowser.open("path_to_file")

This code also works fine in Windows XP Professional, using Internet Explorer 8.


回答 6

如果subprocess.call()要这样做,在Windows上应如下所示:

import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))

您不能只使用:

subprocess.call(('start', FILE_NAME))

因为start 它不是可执行文件,而是cmd.exe程序的命令。这有效:

subprocess.call(('cmd', '/C', 'start', FILE_NAME))

但前提是FILE_NAME中没有空格。

尽管subprocess.call方法en正确引用了参数,但该start命令具有一种相当奇怪的语法,其中:

start notes.txt

除了:

start "notes.txt"

第一个带引号的字符串应设置窗口的标题。要使其与空格配合使用,我们必须执行以下操作:

start "" "my notes.txt"

这是最上面的代码的作用。

If you want to go the subprocess.call() way, it should look like this on Windows:

import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))

You can’t just use:

subprocess.call(('start', FILE_NAME))

because start is not an executable but a command of the cmd.exe program. This works:

subprocess.call(('cmd', '/C', 'start', FILE_NAME))

but only if there are no spaces in the FILE_NAME.

While subprocess.call method enquotes the parameters properly, the start command has a rather strange syntax, where:

start notes.txt

does something else than:

start "notes.txt"

The first quoted string should set the title of the window. To make it work with spaces, we have to do:

start "" "my notes.txt"

which is what the code on top does.


回答 7

开始不支持长路径名和空格。您必须将其转换为8.3兼容路径。

import subprocess
import win32api

filename = "C:\\Documents and Settings\\user\\Desktop\file.avi"
filename_short = win32api.GetShortPathName(filename)

subprocess.Popen('start ' + filename_short, shell=True )

该文件必须存在才能与API调用一起使用。

Start does not support long path names and white spaces. You have to convert it to 8.3 compatible paths.

import subprocess
import win32api

filename = "C:\\Documents and Settings\\user\\Desktop\file.avi"
filename_short = win32api.GetShortPathName(filename)

subprocess.Popen('start ' + filename_short, shell=True )

The file has to exist in order to work with the API call.


回答 8

我已经很晚了,但是这里是使用Windows API的解决方案。这总是打开关联的应用程序。

import ctypes

shell32 = ctypes.windll.shell32
file = 'somedocument.doc'

shell32.ShellExecuteA(0,"open",file,0,0,5)

很多魔术常数。第一个零是当前程序的hwnd。可以为零。另外两个零是可选参数(参数和目录)。5 == SW_SHOW,它指定如何执行应用程序。阅读 ShellExecute API文档以获取更多信息。

I am pretty late to the lot, but here is a solution using the windows api. This always opens the associated application.

import ctypes

shell32 = ctypes.windll.shell32
file = 'somedocument.doc'

shell32.ShellExecuteA(0,"open",file,0,0,5)

A lot of magic constants. The first zero is the hwnd of the current program. Can be zero. The other two zeros are optional parameters (parameters and directory). 5 == SW_SHOW, it specifies how to execute the app. Read the ShellExecute API docs for more info.


回答 9

在Mac OS上,您可以调用“打开”

import os
os.popen("open myfile.txt")

这将使用TextEdit打开该文件,或者将此文件类型设置为默认应用程序

on mac os you can call ‘open’

import os
os.popen("open myfile.txt")

this would open the file with TextEdit, or whatever app is set as default for this filetype


回答 10

如果要指定用于在Mac OS X上打开文件的应用程序,请使用以下命令: os.system("open -a [app name] [file name]")

If you want to specify the app to open the file with on Mac OS X, use this: os.system("open -a [app name] [file name]")


回答 11

在Windows 8.1上,下面的方法已经起作用,而其他给定的方法却subprocess.call失败了,并且路径中有空格。

subprocess.call('cmd /c start "" "any file path with spaces"')

通过之前利用此答案和其他答案,这是一个内联代码,可在多个平台上工作。

import sys, os, subprocess
subprocess.call(('cmd /c start "" "'+ filepath +'"') if os.name is 'nt' else ('open' if sys.platform.startswith('darwin') else 'xdg-open', filepath))

On windows 8.1, below have worked while other given ways with subprocess.call fails with path has spaces in it.

subprocess.call('cmd /c start "" "any file path with spaces"')

By utilizing this and other’s answers before, here’s an inline code which works on multiple platforms.

import sys, os, subprocess
subprocess.call(('cmd /c start "" "'+ filepath +'"') if os.name is 'nt' else ('open' if sys.platform.startswith('darwin') else 'xdg-open', filepath))

回答 12

os.startfile(path, 'open')在Windows下,这是一个好习惯,因为当目录中存在空格时,os.system('start', path_name)无法正确打开应用程序;当目录中存在i18n时,则os.system需要将unicode更改为Windows中控制台的编解码器。

os.startfile(path, 'open') under Windows is good because when spaces exist in the directory, os.system('start', path_name) can’t open the app correctly and when the i18n exist in the directory, os.system needs to change the unicode to the codec of the console in Windows.