如何在Python中获得监视器分辨率?


125

获得监视器分辨率(最好是在元组中)的最简单方法是什么?


您是否在使用特定的UI工具包?(例如GTK,wxPython,Tkinter等)
有意思,2010年

11
使用该Tkinter模块,您可以通过这种方式进行。它是标准Python库的一部分,可在大多数Unix和Windows平台上使用。
martineau,2010年

Answers:


74

在Windows上:

from win32api import GetSystemMetrics

print("Width =", GetSystemMetrics(0))
print("Height =", GetSystemMetrics(1))

如果使用高分辨率屏幕,请确保您的python解释器为HIGHDPIAWARE。

根据这篇文章。


9
有关多平台的完整解决方案,请参阅此答案
Dhruv Reshamwala

1
当使用多台显示器时,这只会返回主显示器的尺寸。
Stevoisiak

1
如何设置python解释器为highdpiaware?将其包含在答案中将很有用。
eric

120

在Windows中,您还可以将ctypes与GetSystemMetrics()以下命令一起使用:

import ctypes
user32 = ctypes.windll.user32
screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)

这样您就不需要安装pywin32软件包;它不需要Python本身没有的任何东西。

对于多显示器设置,您可以检索虚拟显示器的宽度和高度的组合:

import ctypes
user32 = ctypes.windll.user32
screensize = user32.GetSystemMetrics(78), user32.GetSystemMetrics(79)

11
重要说明:如果使用DPI缩放比例,则返回的值可能不正确(即:在4k显示屏上经常出现这种情况),必须在初始化GUI组件之前调用SetProcessDPIAware(而不是在调用GetSystemMetrics函数之前)。对于win32平台上的大多数答案(GTK等),都是如此。
totaam 2014年

1
对于多台监视器,您可以使用GetSystemMetrics(78)和GetSystemMetrics(79)
Derek '18

@Derek什么GetSystemMetrics(78)GetSystemMetrics(79)回报?
Stevoisiak

@StevenVascellaro虚拟屏幕的宽度/高度,以像素为单位。msdn.microsoft.com/en-us/library/windows/desktop/...
德里克

93

为此,我创建了一个PyPI模块

pip install screeninfo

代码:

from screeninfo import get_monitors
for m in get_monitors():
    print(str(m))

结果:

monitor(1920x1080+1920+0)
monitor(1920x1080+0+0)

它支持多监视器环境。其目标是成为跨平台的平台。目前,它支持Cygwin和X11,但完全欢迎请求请求。


2
在Windows上运行良好,但在Mac上却出现以下错误:ImportError:无法加载X11
Chris Lucian

5
在Ubuntu上效果很好。在Ubuntu 16.04上测试。
Dhruv Reshamwala

3
仅供参考,Windows DPI缩放仍适用。此行将告诉Windows您想要原始的,未缩放的分辨率:“ import ctypes; user32 = ctypes.windll.user32; user32.SetProcessDPIAware()”。1)您的答案应该是最重要的;做得好。2)我的评论是Windows特定的,而不是特定于库的(即screeninfo)3)代码从KobeJohn的评论中被撕下并经过测试: stackoverflow.com/a/32541666/2616321
Jason2616321

6
便捷模块(+1)。我必须先安装几个要求(例如pip install cython pyobjus),然后才能在OSX上使用它
George Profenza

45

如果您使用的是wxWindows,则只需执行以下操作:

import wx

app = wx.App(False) # the wx.App object must be created first.    
print(wx.GetDisplaySize())  # returns a tuple

这是最好的一个...谁没有wx?:)再加上几行代码,而不是一堆代码。现在,这是我的默认方法,谢谢。
m3nda

1
这应该是app = wx.App(False)否则,你得到了“wx.App对象必须先创建。” 错误。26票,没有人检查吗?是否可以在Windows中运行而无需将wx实例赋给变量?
m3nda

2
谁没有wx?很多人?
沼泽


29

在Windows 8.1上,我无法从ctypes或tk中获得正确的分辨率。其他人对于ctypes也有同样的问题:getsystemmetrics返回错误的屏幕尺寸 要在Windows 8.1上获得高DPI监视器的正确全分辨率,必须调用SetProcessDPIAware并使用以下代码:

import ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
[w, h] = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]

以下是完整详细信息:

我发现这是因为Windows正在报告缩放的分辨率。看来python默认是“系统dpi感知”应用程序。DPI感知应用程序的类型在此处列出:http : //msdn.microsoft.com/zh-cn/library/windows/desktop/dn469266%28v=vs.85%29.aspx#dpi_and_the_desktop_scaling_factor

基本上,不是将内容显示在整个监视器分辨率上(这会使字体变小),而是按比例放大内容,直到字体足够大为止。

在我的显示器上,我得到:
物理分辨率:2560 x 1440(220 DPI)
报告的python分辨率:1555 x 875(158 DPI)

每个Windows站点:http : //msdn.microsoft.com/zh-cn/library/aa770067%28v=vs.85%29.aspx 报告的系统有效分辨率的公式为:(reported_px * current_dpi)/(96 dpi )= physical_px

我可以使用以下代码获得正确的全屏分辨率和当前的DPI。请注意,我调用SetProcessDPIAware()来允许程序查看实际分辨率。

import tkinter as tk
root = tk.Tk()

width_px = root.winfo_screenwidth()
height_px = root.winfo_screenheight() 
width_mm = root.winfo_screenmmwidth()
height_mm = root.winfo_screenmmheight() 
# 2.54 cm = in
width_in = width_mm / 25.4
height_in = height_mm / 25.4
width_dpi = width_px/width_in
height_dpi = height_px/height_in 

print('Width: %i px, Height: %i px' % (width_px, height_px))
print('Width: %i mm, Height: %i mm' % (width_mm, height_mm))
print('Width: %f in, Height: %f in' % (width_in, height_in))
print('Width: %f dpi, Height: %f dpi' % (width_dpi, height_dpi))

import ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
[w, h] = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]
print('Size is %f %f' % (w, h))

curr_dpi = w*96/width_px
print('Current DPI is %f' % (curr_dpi))    

哪个返回:

Width: 1555 px, Height: 875 px
Width: 411 mm, Height: 232 mm
Width: 16.181102 in, Height: 9.133858 in
Width: 96.099757 dpi, Height: 95.797414 dpi
Size is 2560.000000 1440.000000
Current DPI is 158.045016

我正在使用支持220 DPI的监视器运行Windows 8.1。我的显示比例将我的当前DPI设置为158。

我将使用158来确保我的matplotlib图的大小正确:from pylab import rcParams rcParams ['figure.dpi'] = curr_dpi


您在这里有很多很好的信息,但是答案本身就隐藏在中间。为了使其更容易阅读,您能否确切说明答案是什么,然后提供背景信息?
skrrgwasme 2014年

我编辑了帖子以在开始时显示答案,然后详细介绍。感谢您的反馈。
spacether 2014年

1
看起来这里的计算存在缺陷,很容易发现,您可以根据报告的宽度和高度(以英寸为单位)计算对角线尺寸。我对角线为13.3英寸的屏幕被报告为15英寸。似乎Tkinter使用的是正确的像素,但不知道dpi的缩放比例,因此报告的mm尺寸错误。
2015年

这在Windows 10上不起作用,那里的SetSystemDPIAware()似乎没有什么不同。但是,调用ctypes.windll.shcore.SetProcessDpiAwareness(2)似乎可以解决问题。
克拉默Schutte

@KlamerSchutte:ctypes.windll.shcore.SetProcessDpiAwareness(2)返回错误OSError: [WinError 126] The specified module could not be found
阿德里安·基斯特

21

为了完整起见,Mac OS X

import AppKit
[(screen.frame().size.width, screen.frame().size.height)
    for screen in AppKit.NSScreen.screens()]

将为您提供包含所有屏幕尺寸的元组列表(如果存在多个监视器)


15

如果Qt专门使用工具箱PySide,则可以执行以下操作:

from PySide import QtGui
import sys

app = QtGui.QApplication(sys.argv)
screen_rect = app.desktop().screenGeometry()
width, height = screen_rect.width(), screen_rect.height()


11

这是一个快速的Python小程序,将显示有关多显示器设置的信息:

import gtk

window = gtk.Window()

# the screen contains all monitors
screen = window.get_screen()
print "screen size: %d x %d" % (gtk.gdk.screen_width(),gtk.gdk.screen_height())

# collect data about each monitor
monitors = []
nmons = screen.get_n_monitors()
print "there are %d monitors" % nmons
for m in range(nmons):
  mg = screen.get_monitor_geometry(m)
  print "monitor %d: %d x %d" % (m,mg.width,mg.height)
  monitors.append(mg)

# current monitor
curmon = screen.get_monitor_at_window(screen.get_active_window())
x, y, width, height = monitors[curmon]
print "monitor %d: %d x %d (current)" % (curmon,width,height)  

这是其输出的示例:

screen size: 5120 x 1200
there are 3 monitors
monitor 0: 1600 x 1200
monitor 1: 1920 x 1200
monitor 2: 1600 x 1200
monitor 1: 1920 x 1200 (current)

是否gtk.Window()得到了gdk_default_root_window?您确定这样.get_screen包含所有监视器吗?
yatg

我问,因为在我的代码中,我试图复制您的代码,我正在用jsctypes做它,并且一直告诉我0个监视器:gist.github.com/yajd/55441c9c3d0711ee4a38#file-gistfile1-txt-L3
yatg

2
自从我编写该代码已经有一段时间了,但是,如果我没记错的话,那gtk.Window()是创建一个新窗口(请参见此处)。该窗口只是get_screen获取监视器信息的一种方法。它返回窗口所在的屏幕(或者曾经显示过的窗口)。我猜这是否取决于“ X”配置,即“屏幕”是否包含所有“监视器”。它在Twinview上对我的系统有效。
starfry

谢谢@starfry!我需要找到一个交叉解决方案,该解决方案可以获取所有显示器及其尺寸,而与屏幕无关。你有没有开发类似的东西的机会?:)
yatg 2015年

更高版本的工具包的替代选择:```python
satyagraha

9

我在以下项目之一中使用get_screen_resolution方法,该方法基本上是一个导入链。您可以根据需要进行修改,方法是删除不需要的部分,并在链中向上移动更可能的端口。

PYTHON_V3 = sys.version_info >= (3,0,0) and sys.version_info < (4,0,0):
#[...]
    def get_screen_resolution(self, measurement="px"):
        """
        Tries to detect the screen resolution from the system.
        @param measurement: The measurement to describe the screen resolution in. Can be either 'px', 'inch' or 'mm'. 
        @return: (screen_width,screen_height) where screen_width and screen_height are int types according to measurement.
        """
        mm_per_inch = 25.4
        px_per_inch =  72.0 #most common
        try: # Platforms supported by GTK3, Fx Linux/BSD
            from gi.repository import Gdk 
            screen = Gdk.Screen.get_default()
            if measurement=="px":
                width = screen.get_width()
                height = screen.get_height()
            elif measurement=="inch":
                width = screen.get_width_mm()/mm_per_inch
                height = screen.get_height_mm()/mm_per_inch
            elif measurement=="mm":
                width = screen.get_width_mm()
                height = screen.get_height_mm()
            else:
                raise NotImplementedError("Handling %s is not implemented." % measurement)
            return (width,height)
        except:
            try: #Probably the most OS independent way
                if PYTHON_V3: 
                    import tkinter 
                else:
                    import Tkinter as tkinter
                root = tkinter.Tk()
                if measurement=="px":
                    width = root.winfo_screenwidth()
                    height = root.winfo_screenheight()
                elif measurement=="inch":
                    width = root.winfo_screenmmwidth()/mm_per_inch
                    height = root.winfo_screenmmheight()/mm_per_inch
                elif measurement=="mm":
                    width = root.winfo_screenmmwidth()
                    height = root.winfo_screenmmheight()
                else:
                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                return (width,height)
            except:
                try: #Windows only
                    from win32api import GetSystemMetrics 
                    width_px = GetSystemMetrics (0)
                    height_px = GetSystemMetrics (1)
                    if measurement=="px":
                        return (width_px,height_px)
                    elif measurement=="inch":
                        return (width_px/px_per_inch,height_px/px_per_inch)
                    elif measurement=="mm":
                        return (width_px/mm_per_inch,height_px/mm_per_inch)
                    else:
                        raise NotImplementedError("Handling %s is not implemented." % measurement)
                except:
                    try: # Windows only
                        import ctypes
                        user32 = ctypes.windll.user32
                        width_px = user32.GetSystemMetrics(0)
                        height_px = user32.GetSystemMetrics(1)
                        if measurement=="px":
                            return (width_px,height_px)
                        elif measurement=="inch":
                            return (width_px/px_per_inch,height_px/px_per_inch)
                        elif measurement=="mm":
                            return (width_px/mm_per_inch,height_px/mm_per_inch)
                        else:
                            raise NotImplementedError("Handling %s is not implemented." % measurement)
                    except:
                        try: # Mac OS X only
                            import AppKit 
                            for screen in AppKit.NSScreen.screens():
                                width_px = screen.frame().size.width
                                height_px = screen.frame().size.height
                                if measurement=="px":
                                    return (width_px,height_px)
                                elif measurement=="inch":
                                    return (width_px/px_per_inch,height_px/px_per_inch)
                                elif measurement=="mm":
                                    return (width_px/mm_per_inch,height_px/mm_per_inch)
                                else:
                                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                        except: 
                            try: # Linux/Unix
                                import Xlib.display
                                resolution = Xlib.display.Display().screen().root.get_geometry()
                                width_px = resolution.width
                                height_px = resolution.height
                                if measurement=="px":
                                    return (width_px,height_px)
                                elif measurement=="inch":
                                    return (width_px/px_per_inch,height_px/px_per_inch)
                                elif measurement=="mm":
                                    return (width_px/mm_per_inch,height_px/mm_per_inch)
                                else:
                                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                            except:
                                try: # Linux/Unix
                                    if not self.is_in_path("xrandr"):
                                        raise ImportError("Cannot read the output of xrandr, if any.")
                                    else:
                                        args = ["xrandr", "-q", "-d", ":0"]
                                        proc = subprocess.Popen(args,stdout=subprocess.PIPE)
                                        for line in iter(proc.stdout.readline,''):
                                            if isinstance(line, bytes):
                                                line = line.decode("utf-8")
                                            if "Screen" in line:
                                                width_px = int(line.split()[7])
                                                height_px = int(line.split()[9][:-1])
                                                if measurement=="px":
                                                    return (width_px,height_px)
                                                elif measurement=="inch":
                                                    return (width_px/px_per_inch,height_px/px_per_inch)
                                                elif measurement=="mm":
                                                    return (width_px/mm_per_inch,height_px/mm_per_inch)
                                                else:
                                                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                                except:
                                    # Failover
                                    screensize = 1366, 768
                                    sys.stderr.write("WARNING: Failed to detect screen size. Falling back to %sx%s" % screensize)
                                    if measurement=="px":
                                        return screensize
                                    elif measurement=="inch":
                                        return (screensize[0]/px_per_inch,screensize[1]/px_per_inch)
                                    elif measurement=="mm":
                                        return (screensize[0]/mm_per_inch,screensize[1]/mm_per_inch)
                                    else:
                                        raise NotImplementedError("Handling %s is not implemented." % measurement)

1
感谢您分享此内容,但可以通过使用处理if-else案件的功能将其缩短很多时间
Udayraj Deshmukh

8

旧问题,但这是缺失的。我是python的新手,所以请告诉我这是否是“不好的”解决方案。此解决方案仅在Windows和MacOS上受支持,并且仅在主屏幕上有效-但问题中未提及os。

通过截屏来测量尺寸。由于屏幕尺寸不应更改,因此只能执行一次。如果您安装了GUI工具包(例如GTK,wx,...),则可以使用更优雅的解决方案。

枕头

pip install Pillow

from PIL import ImageGrab

img = ImageGrab.grab()
print (img.size)

6

XWindows版本:

#!/usr/bin/python

import Xlib
import Xlib.display

resolution = Xlib.display.Display().screen().root.get_geometry()
print str(resolution.width) + "x" + str(resolution.height)

6

扩展@ user2366975的答案,以使用Tkinter(Python 2/3中的代码)在多屏幕设置中获取当前屏幕大小:

try:
    # for Python 3
    import tkinter as tk
except ImportError:
    # for Python 2
    import Tkinter as tk


def get_curr_screen_geometry():
    """
    Workaround to get the size of the current screen in a multi-screen setup.

    Returns:
        geometry (str): The standard Tk geometry string.
            [width]x[height]+[left]+[top]
    """
    root = tk.Tk()
    root.update_idletasks()
    root.attributes('-fullscreen', True)
    root.state('iconic')
    geometry = root.winfo_geometry()
    root.destroy()
    return geometry

(应该可以跨平台工作,仅在Linux上进行测试)



5

如果您已安装PyQt4,请尝试以下代码:

from PyQt4 import QtGui
import sys

MyApp = QtGui.QApplication(sys.argv)
V = MyApp.desktop().screenGeometry()
h = V.height()
w = V.width()
print("The screen resolution (width X height) is the following:")
print(str(w) + "X" + str(h))

对于PyQt5,以下操作将起作用:

from PyQt5 import QtWidgets
import sys

MyApp = QtWidgets.QApplication(sys.argv)
V = MyApp.desktop().screenGeometry()
h = V.height()
w = V.width()
print("The screen resolution (width X height) is the following:")
print(str(w) + "X" + str(h))

5

一个跨平台的简单方法是使用几乎所有python版本都随附的TKinter,因此您无需安装任何东西:

import tkinter
root = tkinter.Tk()
root.withdraw()
WIDTH, HEIGHT = root.winfo_screenwidth(), root.winfo_screenheight()

3

使用Linux使用regexp代替第一行,并取出当前的分辨率值。

显示器当前分辨率:0

>>> screen = os.popen("xrandr -q -d :0").readlines()[0]
>>> print screen
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 1920 x 1920
>>> width = screen.split()[7]
>>> print width
1920
>>> height = screen.split()[9][:-1]
>>> print height
1080
>>> print "Current resolution is %s x %s" % (width,height)
Current resolution is 1920 x 1080

这是在xrandr 1.3.5上完成的,我不知道其他版本的输出是否不同,但这应该可以很容易地弄清楚。


遗憾的是,多显示器设置的效果不是很好。不是python的错,但是使用它可能会产生意想不到的结果……
black_puppydog13年

2

要获得每个像素的位数:

import ctypes
user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32

screensize = (user32.GetSystemMetrics(0), user32.GetSystemMetrics(1))
print "screensize =%s"%(str(screensize))
dc = user32.GetDC(None);

screensize = (gdi32.GetDeviceCaps(dc,8), gdi32.GetDeviceCaps(dc,10), gdi32.GetDeviceCaps(dc,12))
print "screensize =%s"%(str(screensize))
screensize = (gdi32.GetDeviceCaps(dc,118), gdi32.GetDeviceCaps(dc,117), gdi32.GetDeviceCaps(dc,12))
print "screensize =%s"%(str(screensize))

gdi32中的参数:

#/// Vertical height of entire desktop in pixels
#DESKTOPVERTRES = 117,
#/// Horizontal width of entire desktop in pixels
#DESKTOPHORZRES = 118,
#/// Horizontal width in pixels
#HORZRES = 8,
#/// Vertical height in pixels
#VERTRES = 10,
#/// Number of bits per pixel
#BITSPIXEL = 12,

2

尝试pyautogui:

import pyautogui
resolution = pyautogui.size()
print(resolution) 

您实际上应该添加一些有关此代码为何起作用的解释-您还可以在代码本身中以当前形式添加注释-它没有提供任何解释可以帮助社区的其他成员了解您要解决的问题/回答问题。但这也是一个很老的问题-可以接受的答案...
ishmaelMakitla '16

2

使用的另一个版本xrandr

import re
from subprocess import run, PIPE

output = run(['xrandr'], stdout=PIPE).stdout.decode()
result = re.search(r'current (\d+) x (\d+)', output)
width, height = map(int, result.groups()) if result else (800, 600)

2

使用pygame

import pygame
pygame.init()
infos = pygame.display.Info()
screen_size = (infos.current_w, infos.current_h)

[1]

但是,如果尝试将窗口设置为屏幕大小,则可能只想执行以下操作:

pygame.display.set_mode((0,0),pygame.FULLSCREEN)

将您的显示设置为全屏模式。[2]


确认它可以在Windows上运行:)多么好的非Windows特定方法!
卢卡斯·切尔温斯基

1

您可以使用PyMouse。要获取屏幕尺寸,只需使用screen_size()属性:

from pymouse import PyMouse
m = PyMouse()
a = m.screen_size()

a将返回一个元组,(X, Y)其中X水平位置和Y垂直位置。

链接到文档中的功能。


1

如果您使用的是Windows操作系统,则可以使用OS模块来获取它:

import os
cmd = 'wmic desktopmonitor get screenheight, screenwidth'
size_tuple = tuple(map(int,os.popen(cmd).read().split()[-2::]))

它将返回一个元组(Y,X),其中Y是垂直大小,X是水平大小。此代码适用于Python 2和Python 3


0

在Linux上,我们可以使用子流程模块

import subprocess
cmd = ['xrandr']
cmd2 = ['grep', '*']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
p2 = subprocess.Popen(cmd2, stdin=p.stdout, stdout=subprocess.PIPE)
p.stdout.close()

resolution_string, junk = p2.communicate()
resolution = resolution_string.split()[0]
resolution = resolution.decode("utf-8") 
width = int(resolution.split("x")[0].strip())
heigth = int(resolution.split("x")[1].strip())

0

对于视网膜屏幕来说有点麻烦,我使用tkinter来获取假尺寸,使用Pilllow抓取来获取实际尺寸:

import tkinter
root = tkinter.Tk()
resolution_width = root.winfo_screenwidth()
resolution_height = root.winfo_screenheight()
image = ImageGrab.grab()
real_width, real_height = image.width, image.height
ratio_width = real_width / resolution_width
ratio_height = real_height/ resolution_height

0

对于更高版本的PyGtk:

import gi
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk

display = Gdk.Display.get_default()
n_monitors = display.get_n_monitors()
print("there are %d monitors" % n_monitors)
for m in range(n_monitors):
  monitor = display.get_monitor(m)
  geometry = monitor.get_geometry()
  print("monitor %d: %d x %d" % (m, geometry.width, geometry.height))

0

对于Linux,您可以使用以下命令:

import gi
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk

s = Gdk.Screen.get_default()
screen_width = s.get_width()
screen_height = s.get_height()
print(screen_width)
print(screen_height)

0

使用pynput库的实用程序脚本。在此处发布参考:

 
from pynput.mouse import Controller as MouseController

def get_screen_size():
    """Utility function to get screen resolution"""

    mouse = MouseController()

    width = height = 0

    def _reset_mouse_position():
        # Move the mouse to the top left of 
        # the screen
        mouse.position = (0, 0)

    # Reset mouse position
    _reset_mouse_position()

    count = 0
    while 1:
        count += 1
        mouse.move(count, 0)
        
        # Get the current position of the mouse
        left = mouse.position[0]

        # If the left doesn't change anymore, then
        # that's the screen resolution's width
        if width == left:
            # Add the last pixel
            width += 1

            # Reset count for use for height
            count = 0
            break

        # On each iteration, assign the left to 
        # the width
        width = left
    
    # Reset mouse position
    _reset_mouse_position()

    while 1:
        count += 1
        mouse.move(0, count)

        # Get the current position of the mouse
        right = mouse.position[1]

        # If the right doesn't change anymore, then
        # that's the screen resolution's height
        if height == right:
            # Add the last pixel
            height += 1
            break

        # On each iteration, assign the right to 
        # the height
        height = right

    return width, height

>>> get_screen_size()
(1920, 1080)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.