本文共 28585 字,大约阅读时间需要 95 分钟。
在 Python 开发过程中,easy_install 是一个非常有用的工具,用于打包和发布 Python 包。而 pip 则是 Python 的默认包管理工具,用于安装和管理 Python 包。以下将详细介绍如何使用 easy_install 打包和发布 Python 包,并解决某些常见问题。
在某些情况下,下载并运行特定的 Python 代码可能会遇到文件类型检测失败的问题。这种情况下,Python 的 mimetypes.py 文件可能需要修改。
当运行下载的 Python 代码时,可能会出现以下错误:
This is a bug in Python: when you try to open a file with a custom extension, Python doesn't know the MIME type.
为了修复这个问题,我们需要修改 Python 的 mimetypes.py 文件,将其扩展名映射正确添加。以下是修复后的 mimetypes.py 文件内容:
"""Guess the MIME type of a file. This module defines two useful functions: guess_type(url, strict=1) -- guess the MIME type and encoding of a URL. guess_extension(type, strict=1) -- guess the extension for a given MIME type. It also contains the following, for tuning the behavior: Data: knownfiles -- list of files to parse. initiated -- flag set when init() has been called. suffix_map -- dictionary mapping suffixes to suffixes. encodings_map -- dictionary mapping suffixes to encodings. types_map -- dictionary mapping suffixes to types. Functions: init([files]) -- parse a list of files, default knownfiles (on Windows, the default values are taken from the registry). read_mime_types(file) -- parse one file, return a dictionary or None."""import osimport sysimport posixpathimport urllibfrom itertools import counttry: import _winregexcept ImportError: _winreg = None__all__ = [ "guess_type", "guess_extension", "guess_all_extensions", "add_type", "read_mime_types", "init"]knownfiles = [ "/etc/mime.types", "/etc/httpd/mime.types", # Mac OS X "/etc/httpd/conf/mime.types", # Apache "/etc/apache/mime.types", # Apache 1 "/etc/apache2/mime.types", # Apache 2 "/usr/local/etc/httpd/conf/mime.types", "/usr/local/lib/netscape/mime.types", "/usr/local/etc/httpd/conf/mime.types", # Apache 1.2 "/usr/local/etc/mime.types", # Apache 1.3]inited = False_db = Noneclass MimeTypes: """MIME-types datastore. This datastore can handle information from mime.types-style files and supports basic determination of MIME type from a filename or URL, and can guess a reasonable extension given a MIME type. """ def __init__(self, filenames=()): global _db if not inited: init() self.encodings_map = encodings_map.copy() self.suffix_map = suffix_map.copy() self.types_map = ({}, {}) # dict for (non-strict, strict) self.types_map_inv = ({}, {}) for (ext, type) in types_map.items(): self.add_type(type, ext, True) for (ext, type) in common_types.items(): self.add_type(type, ext, False) for name in filenames: self.read(name, strict=True) def add_type(self, type, ext, strict=True): """Add a mapping between a type and an extension. When the extension is already known, the new type will replace the old one. When the type is already known, the extension will be added to the list of known extensions. If strict is true, information will be added to the list of standard types, else to the list of non-standard types. """ self.types_map[strict][ext] = type exts = self.types_map_inv[strict].setdefault(type, []) if ext not in exts: exts.append(ext) def guess_type(self, url, strict=True): """Guess the type of a file based on its URL. Return value is a tuple (type, encoding) where type is None if the type can't be guessed (no or unknown suffix) or a string of the form type/subtype, usable for a MIME Content-type header; and encoding is None for no encoding or the name of the program used to encode (e.g. compress or gzip). The mappings are table-driven. Encoding suffixes are case sensitive; type suffixes are first tried case sensitive, then case insensitive. The suffixes .tgz, .taz, and .tz (case sensitive!) are all mapped to '.tar.gz'. (This is table-driven too, using the dictionary suffix_map). Optional `strict' argument when False adds a bunch of commonly found, but non-standard types. """ scheme, url = urllib.splittype(url) if scheme == 'data': # syntax of data URLs: # dataurl := "data:" [ mediatype ] [ ";base64" ] "," data # mediatype := [ type "/" subtype ] *( ";" parameter ) # data := *urlchar # parameter := attribute "=" value comma = url.find(',') if comma < 0: # bad data URL return None, None semi = url.find(';', 0, comma) if semi >= 0: type = url[:semi] else: type = url[:comma] if '=' in type or '/' not in type: type = 'text/plain' return type, None # never compressed, so encoding is None base, ext = posixpath.splitext(url) while ext in self.suffix_map: base, ext = posixpath.splitext(base + self.suffix_map[ext]) if ext in self.encodings_map: encoding = self.encodings_map[ext] base, ext = posixpath.splitext(base) else: encoding = None types_map = self.types_map[True] if ext in types_map: return types_map[ext], encoding elif ext.lower() in types_map: return types_map[ext.lower()], encoding elif strict: return None, encoding types_map = self.types_map[False] if ext in types_map: return types_map[ext], encoding elif ext.lower() in types_map: return types_map[ext.lower()], encoding else: return None, encoding def guess_all_extensions(self, type, strict=True): """Guess the extensions for a file based on its MIME type. Return value is a list of strings giving the possible filename extensions, including the leading dot ('.'). The extension is not guaranteed to have been associated with any particular data stream, but would be mapped to the MIME type `type' by guess_type(). If no extension can be guessed for `type', None is returned. Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ type = type.lower() extensions = self.types_map_inv[True].get(type, []) if not strict: for ext in self.types_map_inv[False].get(type, []): if ext not in extensions: extensions.append(ext) return extensions def guess_extension(self, type, strict=True): """Guess the extension for a file based on its MIME type. Return value is a string giving a filename extension, including the leading dot ('.'). The extension is not guaranteed to have been associated with any particular data stream, but would be mapped to the MIME type `type' by guess_type(). If no extension can be guessed for `type', None is returned. Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ extensions = self.guess_all_extensions(type, strict) if not extensions: return None return extensions[0] def read(self, filename, strict=True): """Read a single mime.types-format file, specified by pathname. If strict is true, information will be added to the list of standard types, else to the list of non-standard types. """ with open(filename) as fp: self.readfp(fp, strict) def readfp(self, fp, strict=True): """Read a single mime.types-format file. If strict is true, information will be added to the list of standard types, else to the list of non-standard types. """ while 1: line = fp.readline() if not line: break words = line.split() for i in range(len(words)): if words[i][0] == '#': del words[i:] break if not words: continue type, suffixes = words[0], words[1:] for suff in suffixes: self.add_type(type, '.' + suff, strict) def read_windows_registry(self, strict=True): """Load the MIME types database from Windows registry. If strict is true, information will be added to the list of standard types, else to the list of non-standard types. """ # Windows only if not _winreg: return def enum_types(mimedb): for i in count(): try: yield _winreg.EnumKey(mimedb, i) except EnvironmentError: break with _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, '') as hkcr: for subkeyname in enum_types(hkcr): try: with _winreg.OpenKey(hkcr, subkeyname) as subkey: # Only check file extensions if not subkeyname.startswith("."): continue # raises EnvironmentError if no 'Content Type' value mimetype, datatype = _winreg.QueryValueEx(subkey, 'Content Type') if datatype != _winreg.REG_SZ: continue try: mimetype = mimetype.encode(default_encoding) subkeyname = subkeyname.encode(default_encoding) except UnicodeEncodeError: continue self.add_type(mimetype, subkeyname, strict) except EnvironmentError: continue def guess_type(self, url, strict=True): """Guess the type of a file based on its URL. Return value is a tuple (type, encoding) where type is None if the type can't be guessed (no or unknown suffix) or a string of the form type/subtype, usable for a MIME Content-type header; and encoding is None for no encoding or the name of the program used to encode (e.g. compress or gzip). The mappings are table-driven. Encoding suffixes are case sensitive; type suffixes are first tried case sensitive, then case insensitive. The suffixes .tgz, .taz and .tz (case sensitive!) are all mapped to ".tar.gz". (This is table-driven too, using the dictionary suffix_map). Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ if _db is None: init() return _db.guess_type(url, strict) def guess_all_extensions(self, type, strict=True): """Guess the extensions for a file based on its MIME type. Return value is a list of strings giving the possible filename extensions, including the leading dot ('.'). The extension is not guaranteed to have been associated with any particular data stream, but would be mapped to the MIME type `type' by guess_type(). If no extension can be guessed for `type', None is returned. Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ if _db is None: init() return _db.guess_all_extensions(type, strict) def guess_extension(self, type, strict=True): """Guess the extension for a file based on its MIME type. Return value is a string giving a filename extension, including the leading dot ('.'). The extension is not guaranteed to have been associated with any particular data stream, but would be mapped to the MIME type `type' by guess_type(). If no extension can be guessed for `type', None is returned. Optional `strict' argument when false adds a bunch of commonly found, but non-standard types. """ if _db is None: init() return _db.guess_extension(type, strict) def add_type(self, type, ext, strict=True): """Add a mapping between a type and an extension. When the extension is already known, the new type will replace the old one. When the type is already known, the extension will be added to the list of known extensions. If strict is true, information will be added to the list of standard types, else to the list of non-standard types. """ if _db is None: init() return _db.add_type(type, ext, strict) def init(files=None): global suffix_map, types_map, encodings_map, common_types, inited, _db inited = True db = MimeTypes() if files is None: if _winreg: db.read_windows_registry() files = knownfiles for file in files: if os.path.isfile(file): db.read(file) encodings_map = db.encodings_map suffix_map = db.suffix_map types_map = db.types_map[True] common_types = db.types_map[False] # Make the DB a global variable now that it is fully initialized _db = dbdef read_mime_types(file): try: f = open(file) except IOError: return None db = MimeTypes() db.readfp(f, True) return db.types_map[True]def _default_mime_types(): global suffix_map, encodings_map, types_map, common_types suffix_map = { '.tgz': '.tar.gz', '.taz': '.tar.gz', '.tz': '.tar.gz', '.tbz2': '.tar.bz2', '.txz': '.tar.xz', } encodings_map = { '.gz': 'gzip', '.Z': 'compress', '.bz2': 'bzip2', '.xz': 'xz', } # Before adding new types, make sure they are either registered with IANA, # at http://www.isi.edu/in-notes/iana/assignments/media-types # or extensions, i.e. using the x- prefix # If you add to these, please keep them sorted! types_map = { '.a': 'application/octet-stream', '.ai': 'application/postscript', '.aif': 'audio/x-aiff', '.aifc': 'audio/x-aiff', '.aiff': 'audio/x-aiff', '.au': 'audio/basic', '.avi': 'video/x-msvideo', '.bat': 'text/plain', '.bcpio': 'application/x-bcpio', '.bin': 'application/octet-stream', '.bmp': 'image/x-ms-bmp', '.c': 'text/plain', '.cdf': 'application/x-cdf', '.cdf': 'application/x-netcdf', '.cpio': 'application/x-cpio', '.csh': 'application/x-csh', '.css': 'text/css', '.dll': 'application/octet-stream', '.doc': 'application/msword', '.dot': 'application/msword', '.dvi': 'application/x-dvi', '.eml': 'message/rfc822', '.eps': 'application/postscript', '.etx': 'text/x-setext', '.exe': 'application/octet-stream', '.gif': 'image/gif', '.gtar': 'application/x-gtar', '.h': 'text/plain', '.hdf': 'application/x-hdf', '.htm': 'text/html', '.html': 'text/html', '.ico': 'image/vnd.microsoft.icon', '.ief': 'image/ief', '.jpe': 'image/jpeg', '.jpeg': 'image/jpeg', '.jpg': 'image/jpeg', '.js': 'application/javascript', '.ksh': 'text/plain', '.latex': 'application/x-latex', '.m1v': 'video/mpeg', '.man': 'application/x-troff-man', '.me': 'application/x-troff-me', '.mht': 'message/rfc822', '.mhtml': 'message/rfc822', '.mif': 'application/x-mif', '.mov': 'video/quicktime', '.movie': 'video/x-sgi-movie', '.mp2': 'audio/mpeg', '.mp3': 'audio/mpeg', '.mp4': 'video/mp4', '.mpa': 'video/mpeg', '.mpe': 'video/mpeg', '.mpeg': 'video/mpeg', '.mpg': 'video/mpeg', '.ms': 'application/x-troff-ms', '.nc': 'application/x-netcdf', '.nws': 'message/rfc822', '.o': 'application/octet-stream', '.obj': 'application/octet-stream', '.oda': 'application/oda', '.p12': 'application/x-pkcs12', '.p7c': 'application/pkcs7-mime', '.pbm': 'image/x-portable-bitmap', '.pdf': 'application/pdf', '.pfx': 'application/x-pkcs12', '.pgm': 'image/x-portable-graymap', '.pl': 'text/plain', '.png': 'image/png', '.pnm': 'image/x-portable-anymap', '.pot': 'application/vnd.ms-powerpoint', '.ppa': 'application/vnd.ms-powerpoint', '.ppm': 'image/x-portable-pixmap', '.pps': 'application/vnd.ms-powerpoint', '.ppt': 'application/vnd.ms-powerpoint', '.ps': 'application/postscript', '.pwz': 'application/vnd.ms-powerpoint', '.py': 'text/x-python', '.pyc': 'application/x-python-code', '.pyo': 'application/x-python-code', '.qt': 'video/quicktime', '.ra': 'audio/x-pn-realaudio', '.ram': 'application/x-pn-realaudio', '.ras': 'image/x-cmu-raster', '.rdf': 'application/xml', '.rgb': 'image/x-rgb', '.roff': 'application/x-troff', '.rtx': 'text/richtext', '.sgm': 'text/x-sgml', '.sgml': 'text/x-sgml', '.sh': 'application/x-sh', '.shar': 'application/x-shar', '.snd': 'audio/basic', '.so': 'application/octet-stream', '.src': 'application/x-wais-source', '.sv4cpio': 'application/x-sv4cpio', '.sv4crc': 'application/x-sv4crc', '.swf': 'application/x-shockwave-flash', '.t': 'application/x-troff', '.tar': 'application/x-tar', '.tcl': 'application/x-tcl', '.tex': 'application/x-tex', '.texi': 'application/x-texinfo', '.texinfo': 'application/x-texinfo', '.tif': 'image/tiff', '.tiff': 'image/tiff', '.tr': 'application/x-troff', '.tsv': 'text/tab-separated-values', '.txt': 'text/plain', '.ustar': 'application/x-ustar', '.vcf': 'text/x-vcard', '.wav': 'audio/x-wav', '.wiz': 'application/msword', '.wsdl': 'application/xml', '.xbm': 'image/x-xbitmap', '.xlb': 'application/vnd.ms-excel', '.xls': 'application/excel', '.xls': 'application/vnd.ms-excel', '.xml': 'text/xml', '.xpdl': 'application/xml', '.xpm': 'image/x-xpixmap', '.xsl': 'application/xml', '.xwd': 'image/x-xwindowdump', '.zip': 'application/zip', } # These are non-standard types, commonly found in the wild. They will only match if strict=0 flag is given to the API methods. Please sort these too common_types = { '.jpg': 'image/jpg', '.mid': 'audio/midi', '.midi': 'audio/midi', '.pct': 'image/pict', '.pic': 'image/pict', '.pict': 'image/pict', '.rtf': 'application/rtf', '.xul': 'text/xul' }if __name__ == '__main__': import getopt USAGE = """Usage: mimetypes.py [options] typeOptions: --help / -h -- print this message and exit --lenient / -l -- additionally search of some common, but non-standard types. --extension / -e -- guess extension instead of typeMore than one type argument may be given.""" def usage(code, msg=''): print(USAGE) if msg: print(msg) sys.exit(code) try: opts, args = getopt.getopt(sys.argv[1:], 'hle', ['help', 'lenient', 'extension']) except getopt.error, msg: usage(1, msg) strict = 1 extension = 0 for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-l', '--lenient'): strict = 0 elif opt in ('-e', '--extension'): extension = 1 for gtype in args: if extension: guess = guess_extension(gtype, strict) if not guess: print("I don't know anything about type", gtype) else: print("guess: ", guess) else: guess, encoding = guess_type(gtype, strict) if not guess: print("I don't know anything about type", gtype) else: print('type:', guess, 'encoding:', encoding) 确保你的 Python 环境正确配置,包括将 python 根目录下的 Scripts 文件夹添加到 PATH 环境变量中。
Scripts 目录到 PATH:PATH="$PATH:/usr/local/bin/python3"
确保将 python3 的路径添加到 PATH 中。3. 现在可以使用 easy_install 来安装 pip 了。
运行以下命令安装 pip:
easy_install pip
为了确保 pip 和 setuptools 正确安装,你可以运行以下脚本:
#!python"""Bootstrap setuptools installationIf you want to use setuptools in your package's setup.py, just include this file in the same directory with it, and add this to the top of your setup.py:```pythonfrom ez_setup import use_setuptoolsuse_setuptools()
If you want to require a specific version of setuptools, set a downloadmirror, or use an alternate download directory, you can do so by supplying the appropriate options to use_setuptools().
This file can also be run as a script to install or upgrade setuptools."""
import osimport shutilimport sysimport tempfileimport tarfileimport optparseimport subprocessimport platformfrom distutils import log
try:from site import USER_SITEexcept ImportError:USER_SITE = None
DEFAULT_VERSION = "1.0"DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):args = (sys.executable,) + argsreturn subprocess.call(args) == 0
def _check_call_py24(cmd, *args, **kwargs):res = subprocess.call(cmd, *args, **kwargs)class CalledProcessError(Exception):passif not res == 0:msg = "Command '%s' return non-zero exit status %d" % (cmd, res)raise CalledProcessError(msg)
vars(subprocess).setdefault('check_call', _check_call_py24)
def _install(tarball, install_args=()):# extracting the tarballtmpdir = tempfile.mkdtemp()log.warn('Extracting in %s', tmpdir)old_wd = os.getcwd()try:os.chdir(tmpdir)tar = tarfile.open(tarball)_extractall(tar)tar.close()# going in the directorysubdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])os.chdir(subdir)log.warn('Now working in %s', subdir)# installinglog.warn('Installing Setuptools')if not _python_cmd('setup.py', 'install', *install_args):log.warn('Something went wrong during the installation.')log.warn('See the error message above.')# exitcode will be 2return 2finally:os.chdir(old_wd)shutil.rmtree(tmpdir)
def _build_egg(egg, tarball, to_dir):# extracting the tarballtmpdir = tempfile.mkdtemp()log.warn('Extracting in %s', tmpdir)old_wd = os.getcwd()try:os.chdir(tmpdir)tar = tarfile.open(tarball)_extractall(tar)tar.close()# going in the directorysubdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])os.chdir(subdir)log.warn('Now working in %s', subdir)# building an egglog.warn('Building a Setuptools egg in %s', to_dir)_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)finally:os.chdir(old_wd)shutil.rmtree(tmpdir)# returning the resultlog.warn(egg)if not os.path.exists(egg):raise IOError('Could not build the egg.')
def _do_download(version, download_base, to_dir, download_delay):egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' % (version, sys.version_info[0], sys.version_info[1]))if not os.path.exists(egg):tarball = download_setuptools(version, download_base, to_dir, download_delay)_build_egg(egg, tarball, to_dir)sys.path.insert(0, egg)# Remove previously-imported pkg_resources if present (see https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).if 'pkg_resources' in sys.modules:del sys.modules['pkg_resources']import setuptoolssetuptools.bootstrap_install_from = egg
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, download_delay=15):# making sure we use the absolute pathto_dir = os.path.abspath(to_dir)was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modulestry:import pkg_resourcesexcept ImportError:return _do_download(version, download_base, to_dir, download_delay)try:pkg_resources.require("setuptools>=" + version)returnexcept pkg_resources.VersionConflict:e = sys.exc_info()[1]if was_imported:sys.stderr.write("The required version of setuptools (>= %s) is not available,\n""and can't be installed while this script is running. Please\n""install a more recent version first, using\n""'easy_install -U setuptools'.\n\n""(Currently using %r)" % (version, e.args[0]))sys.exit(2)else:del pkg_resources, sys.modules['pkg_resources']# reload okreturn _do_download(version, download_base, to_dir, download_delay)except pkg_resources.DistributionNotFound:return _do_download(version, download_base, to_dir, download_delay)
def download_file_powershell(url, target):"""Download the file at url to target using Powershell (which will validate trust). Raise an exception if the command cannot complete."""target = os.path.abspath(target)cmd = ['powershell','-Command', '(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)' % vars(),]subprocess.check_call(cmd)
download_file_powershell.viable = (lambda: platform.system() == 'Windows' and platform.win32_ver()[1] >= '6')
def download_file_curl(url, target):cmd = ['curl', url, '--silent', '--output', target]subprocess.check_call(cmd)
def has_curl():cmd = ['curl', '--version']devnull = open(os.path.devnull, 'wb')try:subprocess.check_call(cmd, stdout=devnull, stderr=devnull)except:return Falsefinally:devnull.close()return True
download_file_curl.viable = has_curl()
def download_file_wget(url, target):cmd = ['wget', url, '--quiet', '--output-document', target]subprocess.check_call(cmd)
def has_wget():cmd = ['wget', '--version']devnull = open(os.path.devnull, 'wb')try:subprocess.check_call(cmd, stdout=devnull, stderr=devnull)except:return Falsefinally:devnull.close()return True
download_file_wget.viable = has_wget()
def download_file_insecure(url, target):"""Use Python to download the file, even though it cannot authenticate the connection."""try:from urllib.request import urlopenexcept ImportError:from urllib2 import urlopensrc = dst = Nonetry:src = urlopen(url)# Read/write all in one block, so we don't create a corrupt file if the download is interrupted.data = src.read()dst = open(target, "wb")dst.write(data)finally:if src:src.close()if dst:dst.close()
download_file_insecure.viable = lambda: True
def get_best_downloader():downloaders = [download_file_powershell,download_file_curl,download_file_wget,download_file_insecure,]for dl in downloaders:if dl.viable():return dl
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, delay=15):"""Download setuptools from a specified location and return its filename."""# making sure we use the absolute pathto_dir = os.path.abspath(to_dir)tgz_name = "setuptools-%s.tar.gz" % versionurl = download_base + tgz_namesaveto = os.path.join(to_dir, tgz_name)if not os.path.exists(saveto):# Avoid repeated downloadslog.warn("Downloading %s", url)downloader = get_best_downloader()downloader(url, saveto)return os.path.realpath(saveto)
def _extractall(self, path=".", members=None):"""Extract all members from the archive to the current working directory and set owner, modification time and permissions on directories afterwards. path' specifies a different directory to extract to.members' is optional and must be a subset of the list returned by getmembers()."""import copyimport operatorfrom tarfile import ExtractErrordirectories = []if members is None:members = selffor tarinfo in members:if tarinfo.isdir():# Extract directories with a safe mode.directories.append(tarinfo)tarinfo = copy.copy(tarinfo)tarinfo.mode = 448 # decimal for oct 0700self.extract(tarinfo, path)# Reverse sort directories.if sys.version_info < (2, 4):def sorter(dir1, dir2):return cmp(dir1.name, dir2.name)directories.sort(sorter)directories.reverse()else:directories.sort(key=operator.attrgetter('name'), reverse=True)# Set correct owner, mtime and filemode on directories.for tarinfo in directories:dirpath = os.path.join(path, tarinfo.name)try:self.chown(tarinfo, dirpath)self.utime(tarinfo, dirpath)self.chmod(tarinfo, dirpath)except ExtractError:e = sys.exc_info()[1]if self.errorlevel > 1:raiseelse:self._dbg(1, "tarfile: %s" % e)
def _build_install_args(options):"""Build the arguments to 'python setup.py install' on the setuptools package."""install_args = []if options.user_install:if sys.version_info < (2, 6):log.warn("--user requires Python 2.6 or later")raise SystemExit(1)install_args.append('--user')return install_args
def _parse_args():"""Parse the command line for options."""parser = optparse.OptionParser()parser.add_option('--user', dest='user_install', action='store_true', default=False,help='install in user site package (requires Python 2.6 or later)')parser.add_option('--download-base', dest='download_base', metavar="URL",default=DEFAULT_URL,help='alternative URL from where to download the setuptools package')options, args = parser.parse_args()# positional arguments are ignoredreturn options
def main(version=DEFAULT_VERSION):"""Install or upgrade setuptools and EasyInstall."""options = _parse_args()tarball = download_setuptools(download_base=options.download_base)return _install(tarball, _build_install_args(options))
if name == 'main':sys.exit(main())
转载地址:http://fsofk.baihongyu.com/