亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

查找哪個Python包提供了特定的導入模塊

查找哪個Python包提供了特定的導入模塊

泛舟湖上清波郎朗 2023-07-27 14:01:29
不要感到困惑,有大量關于安裝 Python 包、如何導入生成的模塊以及列出可用包的問題。但是,如果您沒有 pip 樣式文件或 Pipenv Pipfile ,則--what-provides似乎沒有與pip等效的選項。此問題與上一個問題類似,但要求提供父包,而不是其他元數據。也就是說,這些其他問題并沒有得到很多關注或許多接受的答案 - 例如。如何查找給定模塊的 python 包元數據信息。就這樣砥礪前行&hellip;&hellip;requirements.txt舉例來說,有兩個包(僅舉幾例)將安裝名為的模塊serial- 即pyserial和serial。因此,假設安裝了其中一個軟件包,我們可以使用 pip list 找到它:python3?-m?pip?list?|?grep?serial但是,如果包的名稱與模塊的名稱不匹配,或者您只是想找出要安裝的包(在舊服務器或開發計算機上工作),就會出現問題。您可以檢查導入模塊的路徑 - 這可以給您提供線索。但繼續這個例子......>>> import serial>>> print(serial.__file__)/usr/lib/python3.6/site-packages/serial/__init__.py它位于一個serial目錄中,但實際上只安裝了pyserial ,而不是serial:> python3 -m pip list | grep serialpyserial? ? ? ? ? ? ? ? ?3.4我能想到的最接近的是生成一個可能在依賴子文件上失敗的requirements.txtvia (就像我所做的那樣),或者通過Pipenvpipreqs ./反向檢查依賴關系(這會帶來一整套新問題來完成所有設置):> pipenv graph --reversecymysql==0.9.15ftptool==0.7.1netifaces==0.10.9pip==20.2.2PyQt5-sip==12.8.1? ? - PyQt5==5.15.0 [requires: PyQt5-sip>=12.8,<13]setuptools==50.3.0wheel==0.35.1有誰知道我錯過了一個簡單的解決方案來查找 pip 包提供特定模塊的命令?
查看完整描述

2 回答

?
互換的青春

TA貢獻1797條經驗 獲得超6個贊

使用( 或)packages_distributions()中的函數。例如,在您的情況下, “導入包”的名稱是:importlib.metadataimportlib-metadataserial

import?importlib.metadata??#?or:?`import?importlib_metadata`
importlib.metadata.packages_distributions()['serial']

這應該返回一個包含 的列表,它是“分發包pyserial”的名稱(應該用于pip?-install 的名稱)。

對于較舊的 Python 版本和/或較舊版本的importlib-metadata...

我相信類似以下的內容應該有效:

#!/usr/bin/env python3


import importlib.util

import pathlib


import importlib_metadata


def get_distribution(file_name):

? ? result = None

? ? for distribution in importlib_metadata.distributions():

? ? ? ? try:

? ? ? ? ? ? relative = (

? ? ? ? ? ? ? ? pathlib.Path(file_name)

? ? ? ? ? ? ? ? .relative_to(distribution.locate_file(''))

? ? ? ? ? ? )

? ? ? ? except ValueError:

? ? ? ? ? ? pass

? ? ? ? else:

? ? ? ? ? ? if distribution.files and relative in distribution.files:

? ? ? ? ? ? ? ? result = distribution

? ? ? ? ? ? ? ? break

? ? return result


def alpha():

? ? file_name = importlib.util.find_spec('serial').origin

? ? distribution = get_distribution(file_name)

? ? print("alpha", distribution.metadata['Name'])


def bravo():

? ? import serial

? ? file_name = serial.__file__

? ? distribution = get_distribution(file_name)

? ? print("bravo", distribution.metadata['Name'])


if __name__ == '__main__':

? ? alpha()

? ? bravo()

這只是一個代碼示例,顯示如何獲取特定模塊所屬的已安裝項目的元數據。


重要的是函數get_distribution,它接受文件名作為參數。它可以是模塊或包數據的文件名。如果該文件名屬于環境中安裝的項目(pip install例如通過),則importlib.metadata.Distribution返回該對象。


查看完整回答
反對 回復 2023-07-27
?
狐的傳說

TA貢獻1804條經驗 獲得超3個贊

此問題現已通過 importlib_metadata 庫解決。請參閱提供從“Python 包”到“分發包”的映射,特別是“注釋 2”處理這個確切的問題。因此,請參閱@sinoroc的評論,您可以使用如下內容找到該包(例如,提供模塊“serial”的包“pyserial”):


>>> import importlib_metadata

>>> print(importlib_metadata.packages_distributions()['serial'])

['pyserial']

我提出了以下代碼(合并了提到的 importlib.util.find_spec 方法,但對返回路徑中的 RECORD 文件進行基于 bash 的搜索)。


作為“python3 python_find-module-package.py -m [module-name-here] -d”運行,這也將打印調試。關閉“-d”開關即可僅返回包名稱(和錯誤)。


TLDR:github 上的代碼。


#!/usr/bin/python3


import sys

import os.path

import importlib.util

import importlib_metadata

import pathlib

import subprocess

import argparse

parser = argparse.ArgumentParser()

parser.add_argument("-m", "--module", help="Find matching package for the specified Python module",

? ? ? ? ? ? ? ? ? ? ? ? ? ? type=str)

#parser.add_argument("-u", "--username", help="Database username",

#? ? ? ? ? ? ? ? ? ? ? ? ? ?type=str)

#parser.add_argument("-p", "--password", help="Database password",

#? ? ? ? ? ? ? ? ? ? ? ? ? ?type=str)

parser.add_argument("-d", "--debug", help="Debug messages are enabled",

? ? ? ? ? ? ? ? ? ? ? ? ? ? action="store_true")

args = parser.parse_args()


TESTMODULE='serial'


def debugPrint (message="Nothing"):

? ? if args.debug:

? ? ? ? print ("[DEBUG] %s" % str(message))


class application ():

? ? def __init__(self, argsPassed):

? ? ? ? self.argsPassed = argsPassed

? ? ? ? debugPrint("Got these arguments:\n%s" % (argsPassed))


? ? def run (self):

? ? ? ? #debugPrint("Running with args:\n%s" % (self.argsPassed))

? ? ? ? try:

? ? ? ? ? ? if self.argsPassed.module is not None:

? ? ? ? ? ? ? ? self.moduleName=self.argsPassed.module? #i.e. the module that you're trying to match with a package.

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? self.moduleName=TESTMODULE

? ? ? ? ? ? ? ? print("[WARN] No module name supplied - defaulting to %s!" % (TESTMODULE))

? ? ? ? ? ? self.location=importlib.util.find_spec(self.moduleName).origin

? ? ? ? ? ? debugPrint(self.location)

? ? ? ? except:

? ? ? ? ? ? print("[ERROR] Parsing module name!")

? ? ? ? ? ? exit(1)


? ? ? ? try:

? ? ? ? ? ? self.getPackage()

? ? ? ? except Exception as e:

? ? ? ? ? ? print ("[ERROR] getPackage failed: %s" % str(e))


? ? ? ? try:

? ? ? ? ? ? distResult=self.getDistribution(self.location)

? ? ? ? ? ? self.packageStrDist=distResult.metadata['Name']

? ? ? ? ? ? print(self.packageStrDist)

? ? ? ? except Exception as e:

? ? ? ? ? ? print ("[ERROR] getDistribution failed: %s" % str(e))


? ? ? ? debugPrint("Parent package for \"%s\" is: \"%s\"" % (self.moduleName, self.packageStr))

? ? ? ? return self.packageStr


? ? def getPackage (self):

? ? ? ? locationStr=self.location.split("site-packages/",1)[1]

? ? ? ? debugPrint(locationStr)

? ? ? ? #serial/__init__.py

? ? ? ? locationDir=self.location.split(locationStr,1)[0]

? ? ? ? debugPrint(locationDir)

? ? ? ? #/usr/lib/python3.6/site-packages

? ? ? ? cmd='find \"' + locationDir + '\" -type f -iname \'RECORD\' -printf \'\"%p\"\\n\' | xargs grep \"' + locationStr + '\" -l -Z'

? ? ? ? debugPrint(cmd)

? ? ? ? #find "/usr/lib/python3.6/site-packages" -type f -iname 'RECORD' -printf '"%p"\n' | xargs grep "serial/__init__.py" -l -Z


? ? ? ? #return_code = os.system(cmd)

? ? ? ? #return_code = subprocess.run([cmd], stdout=subprocess.PIPE, universal_newlines=True, shell=False)

? ? ? ? #findResultAll = return_code.stdout

? ? ? ? findResultAll = subprocess.check_output(cmd, shell=True)? ? # Returns stdout as byte array, null terminated.

? ? ? ? findResult = str(findResultAll.decode('ascii').strip().strip('\x00'))

? ? ? ? debugPrint(findResult)

? ? ? ? #/usr/lib/python3.6/site-packages/pyserial-3.4.dist-info/RECORD


? ? ? ? findDir = os.path.split(findResult)

? ? ? ? self.packageStr=findDir[0].replace(locationDir,"")

? ? ? ? debugPrint(self.packageStr)


? ? def getDistribution(self, fileName=TESTMODULE):

? ? ? ? result = None

? ? ? ? for distribution in importlib_metadata.distributions():

? ? ? ? ? ? try:

? ? ? ? ? ? ? ? relative = (pathlib.Path(fileName).relative_to(distribution.locate_file('')))

? ? ? ? ? ? #except ValueError:

? ? ? ? ? ? #except AttributeError:

? ? ? ? ? ? except:

? ? ? ? ? ? ? ? pass

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? if relative in distribution.files:

? ? ? ? ? ? ? ? ? ? result = distribution

? ? ? ? return result


if __name__ == '__main__':

? ? result=1

? ? try:

? ? ? ? prog = application(args)

? ? ? ? result = prog.run()

? ? except Exception as E:

? ? ? ? print ("[ERROR] Prog Exception: %s" % str(E))

? ? finally:

? ? ? ? sys.exit(result)

? ??

# exit the program if we haven't already

print ("Shouldn't get here.")

sys.exit(result)



查看完整回答
反對 回復 2023-07-27
  • 2 回答
  • 0 關注
  • 195 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號