>>> from env_helper import info; info()
页面更新时间: 2024-01-13 09:32:14
运行环境:
Linux发行版本: Debian GNU/Linux 12 (bookworm)
操作系统内核: Linux-6.1.0-16-amd64-x86_64-with-glibc2.36
Python版本: 3.11.2
5.3. 写入矢量数据¶
一个矢量文件可以通过模式 'a'
(append) 打开,也可以通过模式 'w'
(write)写入。 注意:OGR
的 “update”
模式没有独立格式,因此,Fiona不支持。
5.3.1. 添加数据到现有文件¶
>>> import fiona
>>> with fiona.open('/gdata/prov_capital.shp') as c:
>>> rec = next(iter(c))
>>> rec['id'] = '-1'
>>> rec['properties']['CNTRY_NAME'] = 'Gondor'
/tmp/ipykernel_180500/4290745662.py:4: FionaDeprecationWarning: instances of this class -- CRS, geometry, and feature objects -- will become immutable in fiona version 2.0
rec['id'] = '-1'
/tmp/ipykernel_180500/4290745662.py:5: FionaDeprecationWarning: instances of this class -- CRS, geometry, and feature objects -- will become immutable in fiona version 2.0
rec['properties']['CNTRY_NAME'] = 'Gondor'
注意上面的用法,在 Fiona 2.0 后,不可以用这种方法修改对象。
>>> from fiona import os
>>> os.system("cp /gdata/prov_capital.* /tmp")
0
注意,在文件修改前要拷贝备份。
这样,坐标参考系统、 .format
与文件架构就定义完成,所以他不能以只读方式打开,也不能是 'a'
模式。
新的记录用 fiona.collection.Collection.write
的方式写在文件最尾处,因此,该文件的长度就从 48
增加到了 49
。
>>> import os, stat
>>> shp_file = '/tmp/prov_capital'
>>> os.chmod(shp_file + '.shp', stat.S_IRUSR + stat.S_IWUSR)
>>> os.chmod(shp_file + '.dbf', stat.S_IRUSR + stat.S_IWUSR)
>>> os.chmod(shp_file + '.shx', stat.S_IRUSR + stat.S_IWUSR)
>>> with fiona.open(shp_file + '.shp', 'a') as c:
>>> print(len(c))
34
你写入的记录必须匹配文件模式(因为一个文件包含一个记录型)。如果不是的话,会出现
ValueError
的异常。
with fiona.open(shp_file + '.shp', 'a') as c:
c.write({'properties': {'foo': 'bar'}})
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
若忽略一个记录的ID值,可能就会被下一个生成的值替换掉。如果你只是读文件,仅参考上面的即可,
>>> shp_file = '/tmp/prov_capital'
>>> os.chmod(shp_file + '.shp', stat.S_IRUSR + stat.S_IWUSR)
>>> os.chmod(shp_file + '.dbf', stat.S_IRUSR + stat.S_IWUSR)
>>> os.chmod(shp_file + '.shx', stat.S_IRUSR + stat.S_IWUSR)
>>> with fiona.open('/tmp/prov_capital.shp') as c:
>>> records = list(c) # records = c.next()
>>> records[-1]['id']
'33'
>>> records[-1]['properties']['name']
'澳门'
你可能还会看到ID值为 '-1'
,这记录有时可能会被 '48'
替换掉。
fiona.collection.Collection.
是文件集的唯一记录。
fiona.collection.Collection.writerecords
的写入会成为序列值(或迭代器)。
>>> with fiona.open('/tmp/prov_capital.shp', 'a') as c:
>>> c.writerecords([rec, rec,rec])
>>> print(len(c))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In [8], line 2
1 with fiona.open('/tmp/prov_capital.shp', 'a') as c:
----> 2 c.writerecords([rec, rec,rec])
3 print(len(c))
File /usr/lib/python3/dist-packages/fiona/collection.py:551, in Collection.writerecords(self, records)
549 if self.mode not in ("a", "w"):
550 raise OSError("collection not open for writing")
--> 551 self.session.writerecs(records, self)
552 self._len = self.session.get_length()
553 self._bounds = None
File fiona/ogrext.pyx:1344, in fiona.ogrext.WritingSession.writerecs()
ValueError: Record does not match collection schema: KeysView(<fiona.model.Properties object at 0x7f2ad574b550>) != ['lat', 'lon', 'name']
复制。Fiona集有复制功能。以上的代码共复制了3次,而且它们都有独立的ID号。
缓冲。Fiona输出有缓冲功能。在集关闭后,
write
和writerecords
在磁盘内会刷新。你也可以叫作flush
,会定期写进磁盘的缓冲区域。
5.3.2. 写入新文件¶
写一个新文件比添加现有文件要复杂,因为
CRS、格式、模式等都尚未创建,而且这些都是必做的。
解决方法就是上面所述的映射模式。 CRS有映射功能, fiona.drivers
列表基本把可能的CRS映射格式都已列举出来。
>>> with fiona.open('/gdata/prov_capital.shp') as source:
>>> source_driver = source.driver
>>> source_crs = source.crs
>>> source_schema = source.schema
>>> print(source_driver)
ESRI Shapefile
>>>
>>> source_crs
CRS.from_epsg(4326)
>>> from pprint import pprint
>>> pprint(source_schema)
{'geometry': 'Point',
'properties': OrderedDict([('name', 'str:100'),
('lat', 'float:13.11'),
('lon', 'float:13.11')])}
现在创建一个新文件。
>>> c = fiona.open( '/tmp/foo.shp', 'w', driver=source_driver, crs=source_crs, schema=source_schema)
>>> len(c)
0
>>> c.closed
False
>>> len(c)
0
由于对源架构的性能有要求,可以在写入的模式集中使用同一命令,书面文件的字段可与源文件使用同一命令。
ogrinfo '/tmp/foo.shp' foo -so
INFO: Open of `/tmp/foo.shp'
using driver `ESRI Shapefile' successful.
~fiona.collection.Collection.meta
属性可以使复制文件元属性更加容易。
>>> source = fiona.open('/gdata/prov_capital.shp')
>>> sink = fiona.open('/tmp/foo.shp', 'w', **source.meta)
5.3.3. 排序字段(Ordering Record Fields)¶
在Fiona 1.0.1中, fiona.open
的 schema
参数就是一个有序的库列表(键,值),并指定一个序列。
如果给定一个常规库,用输出 ~items
库的方法来排序。例如,
>>> {'bar': 'int', 'foo': 'str'}.keys()
dict_keys(['bar', 'foo'])
{'properties': {'bar': 'int', 'foo': 'str'}}
模式可生成 Shapefile
,第一个字段是 foo
,第二个字段是 bar
。 如果你想要把 bar
作为第一个字段,你必须用一个属性列表项。
另外,要注意在 schema
要声明 geometry
,其类型为 Polygon
,注意大小写。
>>> c = fiona.open( '/tmp/foo2.shp', 'w',schema={'properties': [('bar', 'int'), ('foo', 'str')], 'geometry': 'Polygon'}, driver = 'ESRI Shapefile')
或者使用 OrderedDict
:
>>> from collections import OrderedDict
>>> schema_props = OrderedDict([('bar', 'int'), ('foo', 'str')])
>>> c = fiona.open('/tmp/foo.shp','w',schema={'properties': schema_props, 'geometry': 'Polygon'}, driver = 'ESRI Shapefile')
5.3.4. 坐标和几何类型¶
矢量数据可以定义为二维或三维的结构。
如果你写一个三维坐标 (X, Y, Z)
元组到2D文件( Point 几何模式),
Z
值就不会显示。
如果你写一个二维坐标 (x, y)
元组到3D文件( 3D Point
几何模式),默认的 Z
值就是 0
。