Python call .exe (сделано с помощью pyinstaller в osgeo4w64), но возвращает TypeError - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь создать пакет, чтобы другие программы на других компьютерах могли его использовать. Пакет состоит в том, чтобы просто преобразовать восточную, северную координаты utm в wgs84, поэтому в качестве примера необходимо взять два аргумента -e 234234.534 и -n 234235.5344. И он должен вывести преобразованную координату wgs84 (x, y).

Я на Windows10 64-битной ОС.

Мой подход - написать функцию в python, используя пакеты поставляются с osgeo4w и используют pyinstaller для экспорта его в виде пакета, чтобы я мог вызвать файл .exe.

Когда я запускаю .exe в osgeo4w.bat, он работает. Но когда я просто использую CMD или использую файл python (используя Python38), чтобы вызвать этот файл .exe, он терпит неудачу.

См. Вопросы в нижней части поста.

Вот шаги я взял более подробно:

Вот файл, который я пытаюсь упаковать, чтобы я мог использовать его в других программах (например, python 2.7.5, поставляемый с ArcGIS10.2, или даже использовать CMD в windows).

##utmsa_to_wgs.py

from osgeo import osr
from osgeo import ogr
import sys
import subprocess

EXE_ROOT = r'{0}'.format('/'.join(sys.argv[0].split('\\')[:-1]))
sys.path.insert(0,EXE_ROOT)


def U_W(easting=0, northing=0):
    source = osr.SpatialReference()
    source.ImportFromEPSG(3107)

    target = osr.SpatialReference()
    target.ImportFromEPSG(4326)

    transform = osr.CoordinateTransformation(source, target)

    point = ogr.CreateGeometryFromWkt("POINT ({0} {1})".format(easting, northing))
    point.Transform(transform)
    return str((point.GetX(), point.GetY())) ##e.g. -33.8434, 151.20534
##print (U_W(northing=1681295.7765812099,easting=2491253.6273768987)) ## northing, easting



if __name__=="__main__":
    a = sys.argv
    for i in range(len(a)):
        if a[i] == '-e':
            easting = a[i+1]
        if a[i] == '-n':
            northing = a[i+1]
        if a[i] == '-c':
            exec(' lambda easting, northing : U_W(easting=easting,northing=northing)')
    sys.stdout.write(U_W(easting=easting,northing=northing))
    sys.exit(0)

Чтобы проверить сам файл python, я могу использовать osgeo4w.bat. Тест в порядке:

C:\OSGeo4W64>python convert_utmsa_to_wgs84/convert_utm_wgs.py -n 1681295.7765812099 -e 2491253.6273768987
(-33.86732713160471, 151.2083407968708)
C:\OSGeo4W64>

И перейдите к py3_env в osgeo4w.bat, чтобы проверить снова: Тест в порядке.

C:\OSGeo4W64>py3_env

C:\OSGeo4W64>SET PYTHONHOME=C:\OSGEO4~1\apps\Python37

C:\OSGeo4W64>SET PYTHONPATH=C:\OSGEO4~1\apps\Python37;C:\OSGEO4~1\apps\Python37\Scripts

C:\OSGeo4W64>PATH C:\OSGEO4~1\apps\Python37;C:\OSGEO4~1\apps\Python37\Scripts;{app};C:\Program Files\MiKTeX 2.9\miktex\bin;C:\OSGEO4~1\apps\Python27\Scripts;C:\OSGEO4~1\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\WBem;C:\Program Files\R\R-3.6.3\bin\x64

C:\OSGeo4W64>python convert_utmsa_to_wgs84/convert_utm_wgs.py -n 1681295.7765812099 -e 2491253.6273768987
(-33.86732713160471, 151.2083407968708)
C:\OSGeo4W64>

Теперь, чтобы попробовать сделать .exe, я открыл osgeo4w .bat shell и вызывается по умолчанию env

pyinstaller convert_utmsa_to_wgs84/convert_utm_wgs.py

И проверено ОК:

(-33.86732713160471, 151.2083407968708)
C:\OSGeo4W64>

И попытался использовать py3_env. Тест OK:

C:\OSGeo4W64>py3_env

C:\OSGeo4W64>SET PYTHONHOME=C:\OSGEO4~1\apps\Python37

C:\OSGeo4W64>SET PYTHONPATH=C:\OSGEO4~1\apps\Python37;C:\OSGEO4~1\apps\Python37\Scripts

C:\OSGeo4W64>PATH C:\OSGEO4~1\apps\Python37;C:\OSGEO4~1\apps\Python37\Scripts;{app};C:\Program Files\MiKTeX 2.9\miktex\bin;C:\OSGEO4~1\apps\Python27\Scripts;C:\OSGEO4~1\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\WBem;C:\Program Files\R\R-3.6.3\bin\x64

C:\OSGeo4W64>dist\convert_utm_wgs\convert_utm_wgs.exe -n 1681295.7765812099 -e 2491253.6273768987
(-33.86732713160471, 151.2083407968708)
C:\OSGeo4W64>

Если я сначала попытаюсь перейти к py3_env, а затем с помощью pyinstaller создать файл .exe, а затем проверить, я получу ошибки:

C:\OSGeo4W64>dist\convert_utm_wgs\convert_utm_wgs.exe -n 1681295.7765812099 -e 2491253.6273768987
Traceback (most recent call last):
  File "lib\site-packages\osgeo\__init__.py", line 18, in swig_import_helper
  File "lib\imp.py", line 297, in find_module
ImportError: No module named '_gdal'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "convert_utmsa_to_wgs84\convert_utm_wgs.py", line 2, in <module>
    from osgeo import osr
  File "C:\OSGEO4~1\apps\Python37\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 623, in exec_module
    exec(bytecode, module.__dict__)
  File "lib\site-packages\osgeo\__init__.py", line 41, in <module>
  File "lib\site-packages\osgeo\__init__.py", line 20, in swig_import_helper
ModuleNotFoundError: No module named '_gdal'
[113704] Failed to execute script convert_utm_wgs

И когда Я закрываю osgeo4w.bat и снова открываю его, чтобы он находился в среде по умолчанию, затем снова запускаю тест, я получаю:

enter image description here

В CMD (после изменения в нужный каталог):

C:\OSGeo4W64>C:\OSGeo4W64\dist\convert_utm_wgs\convert_utm_wgs.exe -n 1681295.7765812099 -e 2491253.6273768987
ERROR 1: PROJ: proj_create_from_database: Cannot find proj.db
ERROR 1: PROJ: proj_create_from_database: Cannot find proj.db
ERROR 1: PROJ: proj_create: unrecognized format / unknown name
ERROR 6: Cannot find coordinate operations from `' to `'
Traceback (most recent call last):
  File "convert_utmsa_to_wgs84\convert_utm_wgs.py", line 36, in <module>
    sys.stdout.write(U_W(easting=easting,northing=northing))
  File "convert_utmsa_to_wgs84\convert_utm_wgs.py", line 21, in U_W
    point.Transform(transform)
  File "site-packages\osgeo\ogr.py", line 7036, in Transform
TypeError: in method 'Geometry_Transform', argument 2 of type 'OSRCoordinateTransformationShadow *'
[119504] Failed to execute script convert_utm_wgs

C:\OSGeo4W64>

И с помощью файла test.py:

## test.py
import os
import sys

##result = os.system("""C:/OSGeo4W64/convert_utmsa_to_wgs84/dist/convert_utm_wgs/convert_utm_wgs.exe -n 1681295.7765812099 -e 2491253.6273768987""")
sys.path.insert(0,r'C:/OSGeo4W64/convert_utmsa_to_wgs84/convert_utm_wgs.py')
##print (result)

import subprocess
result = subprocess.Popen(["cmd", "C:/OSGeo4W64/convert_utmsa_to_wgs84/dist/convert_utm_wgs/convert_utm_wgs.exe",  "-n", "1681295.7765812099", "-e", "2491253.6273768987"],stdout=subprocess.PIPE)
print (result.communicate())
##result = subprocess.check_call(["C:/OSGeo4W64/convert_utmsa_to_wgs84/dist/convert_utm_wgs/convert_utm_wgs.exe", "-n", "1681295.7765812099", "-e", "2491253.6273768987"])
##print (result)



def run(cmd):
##    os.environ['PYTHONUNBUFFERED'] = "1"
    proc = subprocess.Popen(cmd,
##        stdin = subprocess.PIPE,
        stdout = subprocess.PIPE,
        stderr = subprocess.STDOUT,
    )
    stdout, stderr = proc.communicate()

    return proc.returncode, stdout, stderr
print (sys.executable)

code, out, err = run([r'C:\\OSGeo4W64\\dist\\convert_utm_wgs\\convert_utm_wgs.exe',
                                       '-n', '1681295.7765812099', '-e','2491253.6273768987'])#  -n 1681295.7765812099 -e 2491253.6273768987'])

print("out: '{}'".format(out))
print("err: '{}'".format(err))
print("exit: {}".format(code))

Вывод:

(b'', None)
C:\Python38\pythonw.exe
out: 'b'ERROR 1: PROJ: proj_create_from_database: Cannot find proj.db\r\nERROR 1: PROJ: proj_create_from_database: Cannot find proj.db\r\nERROR 1: PROJ: proj_create: unrecognized format / unknown name\r\nERROR 6: Cannot find coordinate operations from `\' to `\'\r\n[119696] Failed to execute script convert_utm_wgs\r\nTraceback (most recent call last):\r\n  File "convert_utmsa_to_wgs84\\convert_utm_wgs.py", line 36, in <module>\r\n  File "convert_utmsa_to_wgs84\\convert_utm_wgs.py", line 21, in U_W\r\n  File "site-packages\\osgeo\\ogr.py", line 7036, in Transform\r\nTypeError: in method \'Geometry_Transform\', argument 2 of type \'OSRCoordinateTransformationShadow *\'\r\n''
err: 'None'
exit: 4294967295

У меня три вопроса:

  1. Судя по ошибкам, которые я получаю из test.py и CMD, похоже, что это относится к файлам, внешним по отношению к пакету, созданному pyinstaller. Разве pyinstaller не импортирует все зависимости, чтобы его можно было доставлять самостоятельно (со всеми файлами .dll и т. Д. c)?

  2. Как я могу исправить эти ошибки, которые я получаю в тестах CMD и test.py?

  3. Существует ли более разумный способ сделать эту функцию доступной, чтобы другие программы могли вызывать ее с аргументами -e 2342324.534 -n 2342324.534?

...