Package: unit_parser
# unit_parser: Unit Parser and Conversions<table><tr><td>Build Status</td><td><a href="https://travis-ci.org/rwilson4/unit_parser"><img src="https://travis-ci.org/rwilson4/unit_parser.svg?branch=master&label=Travis%20CI" alt="travis build status" /></a></td></tr><tr><td>Code Coverage</td><td><a href="https://codecov.io/gh/rwilson4/unit_parser"><img src="https://codecov.io/gh/rwilson4/unit_parser/branch/master/graph/badge.svg" /></a></td></tr></table>## InstallingInstall from PyPI:````sh$ pip install unit_parser````## UsageThis library is primarily for parsing strings representing physicalquantities, like "5 feet" or "88 miles_per_hour". It can also be usedfor converting between compatible units and doing basic arithmeticoperations.The parsing function does double duty as a method for convertingbetween units and is thus called "convert".```sh>>> from unit_parser import unit_parser>>> up = unit_parser()>>> up.convert("3 gallons", "liters")11.356235352```It may seem a little strange to have the number as part of the string,but keep in mind this function is used in the context of convertingtext inputs. For convenience, the---perhaps more intuitive---syntaxworks as well:```sh>>> up.convert(3, "gallons", "liters")11.356235352```Note the unit parser must be initialized before being used by callingthe unit_parser() function without any arguments. That uses thebuilt-in unit specification file to define the units recognized bythis library. If a unit is not supported, you can create your own unitspecification file and provide the file name to this function.The next thing we see is that physical quantities and units arerepresented by strings. I find this to be the most intuitive way ofinteracting with physical quantities. (Aside, something like "3gallons" is a physical quantity, while "liters" is a unit.)Since we represent physical quantities by strings, it is trivial touse the convert function to parse an input in unknown units, butensure it is in the appropriate units for the needs of the program.For example, suppose we have a program that does calculations onvolumes of water. Suppose there is an input (e.g. from a JSON file)representing how much volume of water is to be used. The user is freeto specify the input in whatever units are most convenient, e.g. "2gallons". The code that is parsing this input might call:```sh>>> import json>>> from unit_parser import unit_parser>>> up = unit_parser()>>> config = json.load(open('example.json', 'r'))>>> water_volume = config['water_volume']>>> water_volume_liters = up.convert(water_volume, "liters")```In this way, no assumptions need to be made about what units the inputis in. The code requires the water volume to be expressed in liters,but it doesn't need to know or care how it was specified.Although the above example seems trivial, perhaps the most interestingfeature is the flexible unit specification parsing. Units may bespecified by a definition file (built-in, or provide your own!), or bycombinations of units defined in that file.For example, if 'second', 'meter', and 'kilogram' are defined by thefile, the specification 'kilogram_meter_per_second_squared' is validand parsed as expected. These compound specifications consist oftokens separated by underscores. Tokens include previously definedunits like 'kilogram' as well as the special keywords 'per','squared', and 'cubed'.The keyword 'per' may be used at most once per specification anddirects that all subsequent tokens belong in the denominator of theunit.The keywords 'squared' and 'cubed' indicate that the preceding tokenshould be repeated once or twice more, respectively. They cannot bedaisy chained, for example: 'meters_squared_squared' is not permitted,but 'meters_squared_meters_squared' or 'meters_cubed_meters' wouldbe. They also only apply to the preceding token, so'second_second_meter_meter' is equivalent to'second_squared_meter_squared' but not 'second_meter_squared'.Finally, 'second', 'seconds', and 'sec' are not automaticallytreated as equivalent units, but the unit definition file can anddoes create these as if they were aliases. For example, 'seconds'is defined as '1 second'.We also permit simple arithmetic operations on units. There arefunctions "add", "subtract", "multiply", and "divide". Each functiontakes three arguments: two physical quantities, and the desired unitsof the answer.```sh>>> from unit_parser import unit_parser>>> up = unit_parser()>>> up.add("5 meters", "2 feet", "yards")6.13473315836>>> up.subtract("5 meters", "2 feet", "yards")4.80139982502>>> up.multiply("5 meters_per_sec_squared", "2 kg", "pounds")2.248089431>>> up.divide("5 meters", "2 sec", "mph")5.59234073014```As mentioned above, this library ships with a unit specificationfile. It contains many of the most common units, but you may find someglaring omissions. For your particular use case, you may prefer tocreate your own unit specification file and include that with yourapplication. The unit specification file syntax is simple, if notintuitive. The file is plain-text, with key-value pairs separated by acolon. Comments may be included and begin with a pound symbol(#). Units are either specified as primitives, or in terms of otherunits. A primitive definition consists of specifying the signature ofthe unit, which is represented as a vector of non-negativeintegers. For example:````shsecond: [1 0 0]````The entries of this vector correspond to the exponents of units in anarbitrary order that nonetheless needs to be consistent throughout theapplication. We might arbitrarily decide that time units go first,then length, then mass. Then since force has dimension mass timeslength divided by time squared, all units of force have signature [-21 1]. The way we define the second really just tells the program whichindex (the first) corresponds to a particular primitive. A morecomplete specification might look like this:````shsecond: [1 0 0]meter: [0 1 0]kilogram: [0 0 1]minute: 60 secondhour: 60 minute# We can define a newton either like this:newton: 1 kilogram_meter_per_second_squared# or like this:# newton: [-2 1 1]# (first way preferred).````Once we have defined the "primitive" units, it is simple and intuitiveto define other units recursively in terms of previously specifiedunits. For example, the newton could have been defined in terms of itssignature, but it is better to define it in terms of kilograms,meters, and seconds. A pound (of force) could *not* have been definedin terms of its signature, because although it has the same signature,it has a different quantity. Meaning, a pound is *not* equal to onekilogram meter per second squared, and defining units in terms ofsignatures implicitly assumes the quantity is one.The included unit specification file uses MKS (meters, kilograms,seconds) as the base, but as long as the internal specification isconsistent, that is transparent to the user of such a file. A unitspecification file using imperial units as the base would be just asvalid, and the end user would never even notice.If you are the sort of person that enjoys reading esoteric Wikipediapages, the flexible syntax gives the fun opportunity to look up theofficial definitions of units, and using that in the file. Forexample, it turns out the slug, which is a unit of mass in theimperial system, is actually defined as one pound of force times onesecond squared per foot. So this unit of mass is actually defined interms of a unit of force, even though conceptually mass seems like themore primitive notion! The included unit file tries to be faithful tothese definitions. The reader may quite reasonably ask if it makes anydifference. The answer is no, except perhaps for the fun of it. (Ifyou are *not* the sort of person who enjoys reading esoteric Wikipediaarticles, this whole paragraph makes me sound like a weirdo.)Finally, this library ships with a command line utility called"convert". This can be run from the command line like so:````sh$ convert 5 feet to meters1.524````(The "to" is optional, but I find it more intuitive to include it.)