Python36\Scripts 从错误的 python 版本开始

Python36\Scripts starts on wrong python version

所以我制作了一个包,其中包含一个 python 文件,该文件在安装过程中进入 Python36\Scripts。但是在 WinOS 上,我有 3 个全局 python 解释器。

主要是python2.7,第二个是python3.6,第三个是python3.7。

软件包 'my_package' 安装在 python3.6 中的 C:\Python36\Lib\site-packages\my_package 并包含 python 文件 settings.py

脚本'my_script.py'也安装在python3.6 under C:\Python36\Scripts\my_script.py

所以现在你知道我在 cmd my_script.py 中写的问题在哪里,它会 运行 它超过 python2.7 会引发异常,因为它是不 python2.7 友好。

在 UNIX 中,使用 shebang 行可以轻松解决。 如何使用 python3.6 解释器调用 my_script.py。

在你回答之前我试过这个:

包的结构:

  1. my_package
    1. my_package
      • __init_.py
      • settings.py
    2. 脚本
      • __init_.py
      • my_script.py
    3. setup.py

setup.py

from setuptools import setup

with open("README.md", "r") as fh:
    long_description = fh.read()

setup(name='my_package',
      version='0.1.4',
      description='Work in progress',
      long_description=long_description,
      long_description_content_type="text/markdown",
      author=',
      author_email='',
      packages=['my_package'],
      zip_safe=False,
      install_requires=['SQLAlchemy', 'pandas'],
      scripts=['scripts/my_script.py']
      )

my_script.py

from distutils.sysconfig import get_python_lib
sys.stdout.write(get_python_lib())
sys.path.insert(0, get_python_lib())

from my_package.settings import *

调用python script.py时,操作系统找到了文件script.py,所以必须给出script.py的完整路径,即 python c:\python36\scripts\script.py

如果您希望 python 找到脚本,您应该调用 python -m script(没有 .py),它将启动 python 并在 sys.path 中查找名为 script 的模块。您可以只调用 script.py 而没有前面的 python,但这更复杂:

  • 正确的python解释器必须用windows注册为打开*.py个文件时使用的exe,并且一次只能注册一个解释器
  • 目录 c:\python36\scripts 必须在您的路径上

Windows 不使用 #! shebang "protocol" 将执行文件的命令放在文件的第一行

我为这个问题做了一个解决方法,它会很好地工作。现在我没有一个脚本,而是 my_script.py 和 my_scriptV3.py... 现在 my_scriptV3.py 拥有 my_script.py 拥有的所有代码并且 my_script.py 现在是版本帮助用户正确设置要使用的版本的处理程序,并且仅在主 python 解释器为 python 2 的情况下才需要该操作一次,以后每次从 cmd 调用 my_script.py 时它将使用以前的信息并再次调用 my_scriptV3.py,无需任何额外步骤。

以下代码可能对某人有所帮助(未优化):

import os
import sys
import pickle
import getpass
from subprocess import Popen, PIPE, call

python_path = r'C:\Users\{}\Documents\py_config.pkl'.format(getpass.getuser())

if sys.version_info.major < 3:
    check_path = os.path.exists(python_path)
    if check_path is False:
        while True:
            sys.stdout.write('Python 2.x is not supported do you have Python 3.x? [y/n]')
            answer = raw_input()
            sys.stdout.write("\r")
            if answer.lower() not in ['y', 'n', 'yes', 'no']:
                sys.stdout.write("Answer can be y or n. Try again..\n")
                continue
            break

        if answer.lower() in ['y', 'yes']:
            py_versions = {}
            sys.stdout.write('\nSelect Python3 version to use\n')
            p = Popen(['py', '--list'], stdout=PIPE)
            while True:
                line = p.stdout.readline()
                if not line:
                    break
                line = line.strip().strip('-')
                if line.startswith('3'):
                    line = line[:line.find('-')]
                    py_versions.update({len(py_versions): line})
            if not py_versions:
                sys.stdout.write('\nInstall Python 3 to be able to use this framework')
                exit()
            while True:
                options = ""
                for k, v in py_versions.items():
                    options += "[%s] %s\n" % (k,v)
                sys.stdout.write(options)
                answer = raw_input()
                if answer.isdigit() is False:
                    sys.stdout.write("\n Option must be numeric value. Please try again...\n")
                    continue

                selected_option = int(answer)
                if selected_option not in py_versions.keys():
                    sys.stdout.write("\n Option you entered does not exist. Please try again...\n")
                    continue

                py_version = py_versions.get(selected_option)
                if py_version is not None:
                    py_data = {'version': py_version}
                    sys.stdout.write('\nSelected Python version is %s\n' % py_version)
                    sys.stdout.write('\nChecking paths for this Python pleas wait..\n')
                    p = Popen(
                        'py -%s -c "import sys; import os; sys.stdout.write(os.path.dirname(sys.executable))" ' % py_version,
                        stdout=PIPE)
                    lines = p.stdout.readlines()
                    main_path = lines[0]

                    pycon_path = os.path.join(main_path,'Scripts','my_script.py')
                    if os.path.exists(pycon_path) is False:
                        sys.stdout.write("\n Can't locate my_script.py at {0} \n make sure you are using python "
                                         "version where you installed this package then try again...".format(pycon_path))
                        exit()

                    command = 'py -{0} {1}'.format(py_version, pycon_path)
                    py_data.update({'cmd': command})
                    with open(python_path, 'wb') as fw:
                        pickle.dump(py_data, fw)
                    call(command)

                break


        else:
            sys.stdout.write('\nInstall Python 3 to be able to use this framework')
    else:

        with open(python_path, 'rb') as fr:
            data = pickle.load(fr)
            version = data.get('version')
            sys.stdout.write('\nPython version is defined in %s\n'% python_path)
            sys.stdout.write('\nSelected Python version is %s\n' % version)
            cmd = data.get('cmd')
            call(cmd)


else:
    from Scripts.my_scriptv3 import *
    Configuration()