当前位置: 首页 > 后端技术 > Python

翻译:《实用的Python编程》09_01_Packages

时间:2023-03-26 00:09:34 Python

目录|上一节(8.3调试)|下一节(9.2第三方包)9.1包如果我们编写一个更大的程序,我们真的不想在顶层组织它作为单个文件的大集合。本节介绍包。模块任何一个Python源文件都称为模块。#foo.pydefgrok(a):...defspam(b):...导入语句加载并执行模块。#program.pyimportfooa=foo.grok(2)b=foo.spam('Hello')...包与模块对于较大的代码集合,通常将模块组织到包中。#Fromthispcost.pyreport.pyfileparse.py#Tothisporty/__init__.pypcost.pyreport.pyfileparse.py首先,选择一个名称并使用该名称创建一个顶级目录。如上图所示(显然,最重要的第一步是选择名称)。接下来,将__init__.py文件添加到该目录。__init__.py文件可以是一个空文件。最后把源文件放到这个目录下。使用包作为导入的命名空间。这意味着现在有多级导入。importporty.reportport=porty.report.read_portfolio('port.csv')导入语句还有其他变体:'portfolio.csv')这种方法有两个主要问题:同一??包内不同文件之间的导入不起作用。包中的主脚本无效。所以基本上所有导入都是无效的,但除此之外,该程序有效。问题:导入同一包内不同文件之间的导入现在必须在导入时包含包名称。记住这个结构:porty/__init__.pypcost.pyreport.pyfileparse.pyimportexample根据上面的规则修改(同一包内不同文件之间的导入必须包含包名):#report.pyfromportyimportfileparsedefread_portfolio(filename):returnfileparse.parse_csv(...)所有导入都是绝对的,而不是相对的。#report.pyimportfileparse#中断。fileparsenotfound...除了使用包名直接导入相对导入外,还可以使用.引用当前包。#report.pyfrom.importfileparsedefread_portfolio(filename):returnfileparse.parse_csv(...)语法:from.importmodname使用上述语法可以轻松重命名包。问题:作为主脚本在包内运行子模块的主脚本破坏了程序:bash$pythonporty/pcost.py#BREAKS...原因:您正在运行单个脚本,Python不知道包的其余部分(sys.path是错误的)。所有导入都会中断。要解决这个问题,需要以不同的方式运行程序,可以使用-m选项。bash$python-mporty.pcost#WORKS...__init__.py文件这个文件的主要目的是将模块组织在一起。例如:#porty/__init__.pyfrom.pcostimportportfolio_costfrom.reportimportportfolio_report这使得名称在导入时出现在顶层。fromportyimportportfolio_costportfolio_cost('portfolio.csv')而不是使用多级导入:fromportyimportpcostpcost.portfolio_cost('portfolio.csv')脚本的另一种解决方案如前所述,您需要使用-mpackage.module运行包内的脚本。bash%python3-mporty.pcostportfolio.csv还有另一种选择:编写一个新的顶级脚本。#!/usr/bin/envpython3#pcost.pyimportporty.pcostimportsysporty.pcost.main(sys.argv)脚本位于包外。目录结构如下:pcost.py#top-level-scriptporty/#packagedirectory__init__.pypcost.py...ApplicationStructure代码组织和文件结构是应用程序可维护性的关键。Python没有“一刀切”的方法,但适用于多种问题的结构是:porty-app/README.txtscript.py#SCRIPTporty/#LIBRARYCODE__init__.pypcost.pyreport.pyfileparse.py顶级porty-app目录是所有其他内容的容器-这些内容包括文档、顶级脚本、用例等。此外,顶级脚本(如果有的话)需要放在外面代码包(包的上一层)。#!/usr/bin/envpython3#porty-app/script.pyimportsysimportportyporty.report.main(sys.argv)EXERCISE此时我们有一个包含几个程序的目录:pcost.py#计算投资组合costreport.py#makesareportticker.py#制作一个实时的股票报价机同时,还有很多功能各异的配套模块:stock.py#Stockclassportfolio.py#Portfolioclassfileparse.py#CSVparsingtableformat.py#Formattedtablesfollow.py#Followalogfiletypedproperty.py#Typedclassproperties在本练习中,我们将整理这些代码并将它们放入一个公共包中。练习9.1:创建一个简单的包请创建一个名为porty的目录,并将上述所有Python文件放入其中。此外,在porty目录中创建一个空的__init__.py文件。最后,文件目录如下所示:porty/__init__.pyfileparse.pyfollow.pypcost.pyportfolio.pyreport.pystock.pytableformat.pyticker.pytypedproperty.py请将__pycache__目录放在porty目录下消除。此目录包含以前预编译的Python模块。我们想重新开始。尝试在包中导入几个模块:>>>importporty.report>>>importporty.pcost>>>importporty.ticker如果这些导入失败,进入适当的文件来修复模块导入,以便它可以包含相关的进口。例如,importfileparse语句可以这样修改:#report.pyfrom。importfileparse...如果您有类似fromfileparseimportparse_csv的语句,请修改如下代码:#report.pyfrom.fileparseimportparse_csv。..练习9.2:创建应用程序目录将所有代码放在一个“包”中通常是不够的。有时,支持文件、文档、脚本等需要放在porty/目录之外。请创建一个名为porty-app的新目录。然后将我们在练习9.1中创建的porty目录移动到porty-app目录中。接下来,将测试文件Data/portfolio.csv和Data/prices.csv复制到porty-app目录。此外,在porty-app目录中创建一个README.txt文件,其中包含一些关于您自己的信息。现在,代码组织如下:porty-app/portfolio.csvprices.csvREADME.txtporty/__init__.pyfileparse.pyfollow.pypcost.pyportfolio.pyreport.pystock.pytableformat.pyticker。pytypedproperty.py要运行代码,请确保您现在位于顶级目录porty-app/中。例如,从终端运行:shell%cdporty-appshell%python3>>>importporty.report>>>尝试将前面的脚本作为主程序运行:shell%cdporty-appshell%python3-mporty.reportportfolio.csvprices.csvtxtNameSharesPriceChange------------------------------------------AA1009.22-22.98IBM50106.2815.18CAT15035.46-47.98MSFT20020.89-30.34GE9513.48-26.89MSFT5020.89-44.21IBM100106.2835.84通常使用有点奇怪的shell命令可能需要编写顶层脚本来处理奇怪的包。请创建一个生成上述报告的脚本print-report.py:#!/usr/bin/envpython3#print-report.pyimportsysfromporty.reportimportmainmain(sys.argv)并将脚本print-report.py进入顶级目录porty-app/。并确保您可以在porty-app/目录中运行它:shell%cdporty-appshell%python3print-report.pyportfolio.csvprices.csvtxtNameSharesPriceChange-----------------------------------------AA1009.22-22.98IBM50106.2815.18CAT15035.46-47.98MSFT20020.89-30.34GE9513.48-26.89MSFT5020.89-44.21IBM100106.2835.84shell%最后代码的组织结构应该是这样的:porty-app/portfolio.csvprices.csvprint-report.pyREADME.txtporty/__init__.pyfileparse.py跟随。pypcost.pyportfolio.pyreport.pystock.pytableformat.pyticker.pytypedproperty.py目录|上一节(8.3调试)|下一节(9.2第三方包)注:完整翻译见https://github.com/codists/practical-python-zh

猜你喜欢